spessasynth_lib 3.26.5 → 3.26.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../node_modules/spessasynth_core/src/utils/loggin.js", "../node_modules/spessasynth_core/src/utils/other.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js", "../node_modules/spessasynth_core/src/synthetizer/synth_constants.js", "../node_modules/spessasynth_core/src/externals/stbvorbis_sync/stbvorbis_sync.min.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/unit_converter.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/generator.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/volume_envelope.js", "../node_modules/spessasynth_core/src/utils/indexed_array.js", "../node_modules/spessasynth_core/src/midi/midi_message.js", "../node_modules/spessasynth_core/src/utils/xg_hacks.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js", "../node_modules/spessasynth_core/src/utils/byte_functions/string.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/enums.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/system_exclusive.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/modulator.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/controller_tables.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js", "../node_modules/spessasynth_core/src/utils/byte_functions/little_endian.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/riff_chunk.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/igen.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/sdta.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/shdr.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/imod.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/ibag.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/inst.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/pgen.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/pmod.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/pbag.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/phdr.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_sf2/write.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/basic_zone.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/basic_zones.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/combine_zones.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/wsmp.js", "../node_modules/spessasynth_core/src/soundfont/dls/dls_sources.js", "../node_modules/spessasynth_core/src/soundfont/dls/dls_destinations.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/articulator.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/modulator_converter.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/art2.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/rgn2.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/ins.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/lins.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/wave.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/wvpl.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/write_dls/write_dls.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/basic_sample.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/basic_instrument.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/basic_preset.js", "../node_modules/spessasynth_core/src/soundfont/basic_soundfont/basic_soundfont.js", "../node_modules/spessasynth_core/src/soundfont/dls/read_instrument_list.js", "../node_modules/spessasynth_core/src/soundfont/dls/dls_preset.js", "../node_modules/spessasynth_core/src/soundfont/dls/read_instrument.js", "../node_modules/spessasynth_core/src/soundfont/dls/articulator_converter.js", "../node_modules/spessasynth_core/src/soundfont/dls/read_articulation.js", "../node_modules/spessasynth_core/src/soundfont/dls/read_lart.js", "../node_modules/spessasynth_core/src/soundfont/dls/dls_zone.js", "../node_modules/spessasynth_core/src/soundfont/dls/read_region.js", "../node_modules/spessasynth_core/src/soundfont/dls/dls_sample.js", "../node_modules/spessasynth_core/src/soundfont/dls/read_samples.js", "../node_modules/spessasynth_core/src/soundfont/dls/dls_soundfont.js", "../node_modules/spessasynth_core/src/soundfont/read_sf2/samples.js", "../node_modules/spessasynth_core/src/soundfont/read_sf2/generators.js", "../node_modules/spessasynth_core/src/soundfont/read_sf2/zones.js", "../node_modules/spessasynth_core/src/soundfont/read_sf2/presets.js", "../node_modules/spessasynth_core/src/soundfont/read_sf2/instruments.js", "../node_modules/spessasynth_core/src/soundfont/read_sf2/modulators.js", "../node_modules/spessasynth_core/src/soundfont/read_sf2/soundfont.js", "../node_modules/spessasynth_core/src/soundfont/load_soundfont.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/soundfont_manager.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/lowpass_filter.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/modulator_curves.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/modulation_envelope.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/voice.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/stereo_panner.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/snapshot/channel_snapshot.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/lfo.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/render_voice.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/compute_modulator.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/mute_channel.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/portamento_time.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/note_on.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/program_change.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js", "../node_modules/spessasynth_core/src/synthetizer/audio_engine/main_processor.js", "../node_modules/spessasynth_core/src/utils/byte_functions/big_endian.js", "../node_modules/spessasynth_core/src/sequencer/process_event.js", "../node_modules/spessasynth_core/src/sequencer/process_tick.js", "../node_modules/spessasynth_core/src/midi/midi_sequence.js", "../node_modules/spessasynth_core/src/utils/byte_functions/variable_length_quantity.js", "../node_modules/spessasynth_core/src/midi/midi_tools/midi_writer.js", "../node_modules/spessasynth_core/src/utils/sysex_detector.js", "../node_modules/spessasynth_core/src/midi/midi_tools/midi_editor.js", "../node_modules/spessasynth_core/src/midi/midi_tools/rmidi_writer.js", "../node_modules/spessasynth_core/src/midi/midi_tools/used_keys_loaded.js", "../node_modules/spessasynth_core/src/midi/midi_tools/get_note_times.js", "../node_modules/spessasynth_core/src/midi/basic_midi.js", "../node_modules/spessasynth_core/src/sequencer/song_control.js", "../node_modules/spessasynth_core/src/sequencer/play.js", "../node_modules/spessasynth_core/src/sequencer/events.js", "../node_modules/spessasynth_core/src/sequencer/sequencer_engine.js", "../node_modules/spessasynth_core/src/externals/fflate/fflate.min.js", "../node_modules/spessasynth_core/src/midi/xmf_loader.js", "../node_modules/spessasynth_core/src/midi/midi_loader.js", "../node_modules/spessasynth_core/index.js", "../utils/other.js", "worklet_message.js", "worklet_url.js", "key_modifier_manager.js", "sfman_message.js", "../sequencer/sequencer_message.js", "../utils/fill_with_defaults.js", "../sequencer/default_sequencer_options.js", "../sequencer/midi_data.js", "worklet_processor.js"],
4
- "sourcesContent": ["let ENABLE_INFO = false;\nlet ENABLE_WARN = true;\nlet ENABLE_GROUP = false;\nlet ENABLE_TABLE = true;\n\n/**\n * Enables or disables looging\n * @param enableInfo {boolean} - enables info\n * @param enableWarn {boolean} - enables warning\n * @param enableGroup {boolean} - enables groups\n * @param enableTable {boolean} - enables tables\n */\nexport function SpessaSynthLogging(enableInfo, enableWarn, enableGroup, enableTable)\n{\n ENABLE_INFO = enableInfo;\n ENABLE_WARN = enableWarn;\n ENABLE_GROUP = enableGroup;\n ENABLE_TABLE = enableTable;\n}\n\n/**\n * @param message {...any}\n */\nexport function SpessaSynthInfo(...message)\n{\n if (ENABLE_INFO)\n {\n console.info(...message);\n }\n}\n\n/**\n * @param message {...any}\n */\nexport function SpessaSynthWarn(...message)\n{\n if (ENABLE_WARN)\n {\n console.warn(...message);\n }\n}\n\n/**\n * @param message {...any} the message\n */\nexport function SpessaSynthGroup(...message)\n{\n if (ENABLE_GROUP)\n {\n console.group(...message);\n }\n}\n\n/**\n * @param message {...any} the message\n */\nexport function SpessaSynthGroupCollapsed(...message)\n{\n if (ENABLE_GROUP)\n {\n console.groupCollapsed(...message);\n }\n}\n\nexport function SpessaSynthGroupEnd()\n{\n if (ENABLE_GROUP)\n {\n console.groupEnd();\n }\n}", "/**\n * other.js\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 {number} time in seconds\n * @return {{seconds: number, minutes: number, time: string}}\n */\nexport function formatTime(totalSeconds)\n{\n totalSeconds = Math.floor(totalSeconds);\n let minutes = Math.floor(totalSeconds / 60);\n let 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 * @param fileName {string}\n * @returns {string}\n */\nexport function formatTitle(fileName)\n{\n return fileName\n .trim()\n .replaceAll(\".mid\", \"\")\n .replaceAll(\".kar\", \"\")\n .replaceAll(\".rmi\", \"\")\n .replaceAll(\".xmf\", \"\")\n .replaceAll(\".mxmf\", \"\")\n .replaceAll(\"_\", \" \")\n .trim();\n}\n\n/**\n * Does what it says\n * @param arr {number[]|Uint8Array}\n * @returns {string}\n */\nexport function arrayToHexString(arr)\n{\n let hexString = \"\";\n \n for (let i = 0; i < arr.length; i++)\n {\n const hex = arr[i].toString(16).padStart(2, \"0\").toUpperCase();\n hexString += hex;\n hexString += \" \";\n }\n \n return hexString;\n}\n\n/**\n * @param eventData {Uint8Array}\n * @returns {Uint8Array}\n */\nexport function sanitizeKarLyrics(eventData)\n{\n // for KAR files:\n // https://www.mixagesoftware.com/en/midikit/help/HTML/karaoke_formats.html\n // \"/\" is the newline character\n // \"\\\" is also the newline character\n // \"\\\" ASCII code is 92\n // \"/\" ASCII code is 47\n // newline ASCII code is 10\n const sanitized = [];\n for (let byte of eventData)\n {\n if (byte === 47 || byte === 92)\n {\n byte = 10;\n }\n sanitized.push(byte);\n }\n return new Uint8Array(sanitized);\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\n\n", "/**\n * @param channel {MidiAudioChannel}\n * @param voice {Voice}\n * @return {number}\n */\nfunction getPriority(channel, voice)\n{\n let priority = 0;\n if (channel.drumChannel)\n {\n // important\n priority += 5;\n }\n if (voice.isInRelease)\n {\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 {\n priority -= 5;\n }\n priority -= voice.volumeEnvelope.currentAttenuationDb / 50;\n return priority;\n}\n\n/**\n * @this {SpessaSynthProcessor}\n * @param amount {number}\n */\nexport function voiceKilling(amount)\n{\n let allVoices = [];\n for (const channel of this.midiAudioChannels)\n {\n for (const voice of channel.voices)\n {\n if (!voice.finished)\n {\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 {\n const index = channel.voices.indexOf(voice);\n if (index > -1)\n {\n channel.voices.splice(index, 1);\n }\n }\n}\n\n", "/**\n * Synthesizer's default voice cap\n * @type {number}\n */\nexport const VOICE_CAP = 350;\n/**\n * Default MIDI drum channel\n * @type {number}\n */\nexport const DEFAULT_PERCUSSION = 9;\n/**\n * MIDI channel count\n * @type {number}\n */\nexport const MIDI_CHANNEL_COUNT = 16;\n/**\n * Default bank select and SysEx mode\n * @type {string}\n */\nexport const DEFAULT_SYNTH_MODE = \"gs\";\n\nexport const ALL_CHANNELS_OR_DIFFERENT_ACTION = -1;", "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/RwRAIAUgAUECdGohBCAEKAIAIQYgCSgCACEEQQEgA3QhByAHQX9qIQcgBCAHcSEHIAYgB0YNAQsgAUEBaiEBIAEgAkgNAQwDCwsgAEHoCmohACAAKAIAIQIgAiADSARAIABBADYCAEF/IQEFIAggAWohBSAEIAN2IQMgCSADNgIAIAUtAAAhAyADQf8BcSEDIAIgA2shAiAAIAI2AgALDAILCyAAQRUQFSAAQegKaiEAIABBADYCAEF/IQELIAELXgECfyAEIANrIQQgAiABayECIARBf0ohBUEAIARrIQYgBCAGIAUbIQUgACABayEAIAUgAGwhACAAIAJtIQAgBEEASCEBQQAgAGshAiACIAAgARshACAAIANqIQAgAAv7GgEcfyMGIRwjBkEQaiQGIBxBBGohCSAcIRIgAEGAA2ohCiAKKAIAIQ0gAEGAAmogBEEBdGohCiAKLgEAIQogCkH//wNxIRkgDSAEQRhsakENaiEaIBotAAAhDiAOQf8BcSEOIABB8ABqIRUgFSgCACEQIBAgDkGwEGxqIQ4gDigCACEYIApBAkYhDCADIAx0IQogDSAEQRhsaiEWIBYoAgAhDiAOIApJIRAgDiAKIBAbIRAgDSAEQRhsakEEaiEOIA4oAgAhDiAOIApJIRQgDiAKIBQbIQogCiAQayEKIA0gBEEYbGpBCGohFCAUKAIAIQ4gCiAObiEQIABB0ABqIR4gHigCACEfIABBxABqIQogCigCACEKIApFIQ4gAEEEaiETIBMoAgAhCiAQQQJ0IQYgBkEEaiEHIAogB2whByAOBEAjBiEOIwYgB0EPakFwcWokBgUgACAHEDwhDiATKAIAIQoLIA4gCiAGEDsaIAJBAEoiBgRAIANBAnQhE0EAIQoDQCAFIApqIQcgBywAACEHIAdFBEAgASAKQQJ0aiEHIAcoAgAhByAHQQAgExB6GgsgCkEBaiEKIAogAkcNAAsLIAJBAUchCgJAIAogDHEEQAJAIAYEQEEAIQoDQCAFIApqIQwgDCwAACEMIAxFDQIgCkEBaiEKIAogAkgNAAsFQQAhCgsLIAogAkcEQCAQQQBKIREgAEHoCmohDCAYQQBKIQ8gAEHkCmohEyANIARBGGxqQRRqIRkgDSAEQRhsakEQaiEbQQAhCgJAA0ACQAJAAkACQCACQQFrDgIBAAILIBEEQCAKRSEXQQAhBEEAIQ0DQCAWKAIAIQUgFCgCACEGIAYgBGwhBiAGIAVqIQUgBUEBcSEGIAkgBjYCACAFQQF1IQUgEiAFNgIAIBcEQCAVKAIAIQYgGi0AACEFIAVB/wFxIQcgBiAHQbAQbGohCyAMKAIAIQUgBUEKSARAIAAQNAsgEygCACEIIAhB/wdxIQUgBiAHQbAQbGpBJGogBUEBdGohBSAFLgEAIQUgBUF/SgRAIAYgB0GwEGxqQQhqIQsgCygCACELIAsgBWohCyALLQAAIQsgC0H/AXEhCyAIIAt2IQggEyAINgIAIAwoAgAhCCAIIAtrIQggCEEASCELQQAgCCALGyEIQX8gBSALGyEFIAwgCDYCAAUgACALEDUhBQsgBiAHQbAQbGpBF2ohCCAILAAAIQggCARAIAYgB0GwEGxqQagQaiEGIAYoAgAhBiAGIAVBAnRqIQUgBSgCACEFCyAFQX9GDQcgGygCACEGIAYgBUECdGohBSAFKAIAIQUgDigCACEGIAYgDUECdGohBiAGIAU2AgALIAQgEEghBSAFIA9xBEBBACEFA0AgFCgCACEGIA4oAgAhByAHIA1BAnRqIQcgBygCACEHIAcgBWohByAHLQAAIQcgB0H/AXEhByAZKAIAIQggCCAHQQR0aiAKQQF0aiEHIAcuAQAhByAHQX9KBEAgFSgCACEIIAggB0GwEGxqIQcgACAHIAFBAiAJIBIgAyAGED0hBiAGRQ0JBSAWKAIAIQcgBiAEbCEIIAggBmohBiAGIAdqIQYgBkEBcSEHIAkgBzYCACAGQQF1IQYgEiAGNgIACyAFQQFqIQUgBEEBaiEEIAUgGEghBiAEIBBIIQcgByAGcQ0ACwsgDUEBaiENIAQgEEgNAAsLDAILIBEEQCAKRSEXQQAhDUEAIQQDQCAWKAIAIQUgFCgCACEGIAYgBGwhBiAGIAVqIQUgCUEANgIAIBIgBTYCACAXBEAgFSgCACEGIBotAAAhBSAFQf8BcSEHIAYgB0GwEGxqIQsgDCgCACEFIAVBCkgEQCAAEDQLIBMoAgAhCCAIQf8HcSEFIAYgB0GwEGxqQSRqIAVBAXRqIQUgBS4BACEFIAVBf0oEQCAGIAdBsBBsakEIaiELIAsoAgAhCyALIAVqIQsgCy0AACELIAtB/wFxIQsgCCALdiEIIBMgCDYCACAMKAIAIQggCCALayEIIAhBAEghC0EAIAggCxshCEF/IAUgCxshBSAMIAg2AgAFIAAgCxA1IQULIAYgB0GwEGxqQRdqIQggCCwAACEIIAgEQCAGIAdBsBBsakGoEGohBiAGKAIAIQYgBiAFQQJ0aiEFIAUoAgAhBQsgBUF/Rg0GIBsoAgAhBiAGIAVBAnRqIQUgBSgCACEFIA4oAgAhBiAGIA1BAnRqIQYgBiAFNgIACyAEIBBIIQUgBSAPcQRAQQAhBQNAIBQoAgAhBiAOKAIAIQcgByANQQJ0aiEHIAcoAgAhByAHIAVqIQcgBy0AACEHIAdB/wFxIQcgGSgCACEIIAggB0EEdGogCkEBdGohByAHLgEAIQcgB0F/SgRAIBUoAgAhCCAIIAdBsBBsaiEHIAAgByABQQEgCSASIAMgBhA9IQYgBkUNCAUgFigCACEHIAYgBGwhCCAIIAZqIQYgBiAHaiEGIAlBADYCACASIAY2AgALIAVBAWohBSAEQQFqIQQgBSAYSCEGIAQgEEghByAHIAZxDQALCyANQQFqIQ0gBCAQSA0ACwsMAQsgEQRAIApFIRdBACENQQAhBANAIBYoAgAhBSAUKAIAIQYgBiAEbCEGIAYgBWohBSAFIAUgAm0iBSACbGshBiAJIAY2AgAgEiAFNgIAIBcEQCAVKAIAIQYgGi0AACEFIAVB/wFxIQcgBiAHQbAQbGohCyAMKAIAIQUgBUEKSARAIAAQNAsgEygCACEIIAhB/wdxIQUgBiAHQbAQbGpBJGogBUEBdGohBSAFLgEAIQUgBUF/SgRAIAYgB0GwEGxqQQhqIQsgCygCACELIAsgBWohCyALLQAAIQsgC0H/AXEhCyAIIAt2IQggEyAINgIAIAwoAgAhCCAIIAtrIQggCEEASCELQQAgCCALGyEIQX8gBSALGyEFIAwgCDYCAAUgACALEDUhBQsgBiAHQbAQbGpBF2ohCCAILAAAIQggCARAIAYgB0GwEGxqQagQaiEGIAYoAgAhBiAGIAVBAnRqIQUgBSgCACEFCyAFQX9GDQUgGygCACEGIAYgBUECdGohBSAFKAIAIQUgDigCACEGIAYgDUECdGohBiAGIAU2AgALIAQgEEghBSAFIA9xBEBBACEFA0AgFCgCACEGIA4oAgAhByAHIA1BAnRqIQcgBygCACEHIAcgBWohByAHLQAAIQcgB0H/AXEhByAZKAIAIQggCCAHQQR0aiAKQQF0aiEHIAcuAQAhByAHQX9KBEAgFSgCACEIIAggB0GwEGxqIQcgACAHIAEgAiAJIBIgAyAGED0hBiAGRQ0HBSAWKAIAIQcgBiAEbCEIIAggBmohBiAGIAdqIQYgBiAGIAJtIgYgAmxrIQcgCSAHNgIAIBIgBjYCAAsgBUEBaiEFIARBAWohBCAFIBhIIQYgBCAQSCEHIAcgBnENAAsLIA1BAWohDSAEIBBIDQALCwsgCkEBaiEKIApBCEkNAAsLCwUgEEEASiEbIAJBAUghCCAYQQBKIQsgAEHoCmohEyAAQeQKaiEHIA0gBEEYbGpBEGohFyANIARBGGxqQRRqISBBACEKA0AgGwRAIApBAEcgCHIhIUEAIQ1BACEDA0AgIUUEQEEAIRIDQCAFIBJqIQQgBCwAACEEIARFBEAgFSgCACEJIBotAAAhBCAEQf8BcSEMIAkgDEGwEGxqIQ8gEygCACEEIARBCkgEQCAAEDQLIAcoAgAhESARQf8HcSEEIAkgDEGwEGxqQSRqIARBAXRqIQQgBC4BACEEIARBf0oEQCAJIAxBsBBsakEIaiEPIA8oAgAhDyAPIARqIQ8gDy0AACEPIA9B/wFxIQ8gESAPdiERIAcgETYCACATKAIAIREgESAPayERIBFBAEghD0EAIBEgDxshEUF/IAQgDxshBCATIBE2AgAFIAAgDxA1IQQLIAkgDEGwEGxqQRdqIREgESwAACERIBEEQCAJIAxBsBBsakGoEGohCSAJKAIAIQkgCSAEQQJ0aiEEIAQoAgAhBAsgBEF/Rg0HIBcoAgAhCSAJIARBAnRqIQQgBCgCACEEIA4gEkECdGohCSAJKAIAIQkgCSANQQJ0aiEJIAkgBDYCAAsgEkEBaiESIBIgAkgNAAsLIAMgEEghBCAEIAtxBEBBACESA0AgBgRAQQAhBANAIAUgBGohCSAJLAAAIQkgCUUEQCAOIARBAnRqIQkgCSgCACEJIAkgDUECdGohCSAJKAIAIQkgCSASaiEJIAktAAAhCSAJQf8BcSEJICAoAgAhDCAMIAlBBHRqIApBAXRqIQkgCS4BACEJIAlBf0oEQCABIARBAnRqIQwgDCgCACERIBYoAgAhDyAUKAIAIQwgDCADbCEdIB0gD2ohDyAVKAIAIR0gHSAJQbAQbGohCSAAIAkgESAPIAwgGRA+IQkgCUUNCgsLIARBAWohBCAEIAJIDQALCyASQQFqIRIgA0EBaiEDIBIgGEghBCADIBBIIQkgCSAEcQ0ACwsgDUEBaiENIAMgEEgNAAsLIApBAWohCiAKQQhJDQALCwsgHiAfNgIAIBwkBgvPAwIIfwJ9IANBAXUhCSABQQRqIQMgAygCACEDIAMgAkEDbGpBAmohAiACLQAAIQIgAkH/AXEhAiABQQlqIAJqIQEgAS0AACEBIAFB/wFxIQcgAEH4AGogB0EBdGohASABLgEAIQEgAQRAIABB+AFqIQAgACgCACEIIAUuAQAhASAIIAdBvAxsakG0DGohCyALLQAAIQAgAEH/AXEhACAAIAFsIQEgCCAHQbwMbGpBuAxqIQwgDCgCACECIAJBAUoEQEEAIQBBASEKA0AgCCAHQbwMbGpBxgZqIApqIQMgAy0AACEDIANB/wFxIQ0gBSANQQF0aiEDIAMuAQAhBiAGQX9KBEAgCy0AACEDIANB/wFxIQMgAyAGbCEDIAggB0G8DGxqQdICaiANQQF0aiEGIAYvAQAhBiAGQf//A3EhBiAAIAZHBEAgBCAAIAEgBiADIAkQQiAGIQAgDCgCACECCyADIQELIApBAWohAyADIAJIBEAgAyEKDAELCwVBACEACyAAIAlIBEAgAUECdEGgCGoqAgAhDwNAIAQgAEECdGohASABKgIAIQ4gDyAOlCEOIAEgDjgCACAAQQFqIQAgACAJRw0ACwsFIABBFRAVCwuFGgIVfwp9IwYhFiABQQF1IQ8gAUECdSENIAFBA3UhDiACQdAAaiEUIBQoAgAhFyACQcQAaiEIIAgoAgAhCCAIRSEIIA9BAnQhBSAIBEAjBiEMIwYgBUEPakFwcWokBgUgAiAFEDwhDAsgAkGgCGogA0ECdGohCCAIKAIAIQggD0F+aiEGIAwgBkECdGohBiAAIA9BAnRqIRUgDwR/IAVBcGohBSAFQQR2IQcgB0EDdCEEIAUgBGshBSAMIAVqIQQgB0EBdCEFIAVBAmohCyAGIQcgACEGIAghBQNAIAYqAgAhGSAFKgIAIRogGSAalCEZIAZBCGohCiAKKgIAIRogBUEEaiEJIAkqAgAhGyAaIBuUIRogGSAakyEZIAdBBGohECAQIBk4AgAgBioCACEZIAkqAgAhGiAZIBqUIRkgCioCACEaIAUqAgAhGyAaIBuUIRogGSAakiEZIAcgGTgCACAHQXhqIQcgBUEIaiEFIAZBEGohBiAGIBVHDQALIAQhBiAIIAtBAnRqBSAICyEHIAYgDE8EQCAPQX1qIQQgBiEFIAAgBEECdGohBCAHIQYDQCAEQQhqIQcgByoCACEZIAYqAgAhGiAZIBqUIRkgBCoCACEaIAZBBGohCiAKKgIAIRsgGiAblCEaIBogGZMhGSAFQQRqIQkgCSAZOAIAIAcqAgAhGSAKKgIAIRogGSAalCEZIAQqAgAhGiAGKgIAIRsgGiAblCEaIBqMIRogGiAZkyEZIAUgGTgCACAFQXhqIQUgBkEIaiEGIARBcGohBCAFIAxPDQALCyABQRBOBEAgD0F4aiEGIAggBkECdGohBiAAIA1BAnRqIQcgACEEIAwgDUECdGohCiAMIQUDQCAKQQRqIQkgCSoCACEZIAVBBGohCSAJKgIAIRogGSAakyEbIAoqAgAhHCAFKgIAIR0gHCAdkyEcIBkgGpIhGSAHQQRqIQkgCSAZOAIAIAoqAgAhGSAFKgIAIRogGSAakiEZIAcgGTgCACAGQRBqIQkgCSoCACEZIBsgGZQhGSAGQRRqIQsgCyoCACEaIBwgGpQhGiAZIBqTIRkgBEEEaiEQIBAgGTgCACAJKgIAIRkgHCAZlCEZIAsqAgAhGiAbIBqUIRogGSAakiEZIAQgGTgCACAKQQxqIQkgCSoCACEZIAVBDGohCSAJKgIAIRogGSAakyEbIApBCGohCSAJKgIAIRwgBUEIaiELIAsqAgAhHSAcIB2TIRwgGSAakiEZIAdBDGohECAQIBk4AgAgCSoCACEZIAsqAgAhGiAZIBqSIRkgB0EIaiEJIAkgGTgCACAGKgIAIRkgGyAZlCEZIAZBBGohCSAJKgIAIRogHCAalCEaIBkgGpMhGSAEQQxqIQsgCyAZOAIAIAYqAgAhGSAcIBmUIRkgCSoCACEaIBsgGpQhGiAZIBqSIRkgBEEIaiEJIAkgGTgCACAGQWBqIQYgB0EQaiEHIARBEGohBCAKQRBqIQogBUEQaiEFIAYgCE8NAAsLIAEQLSEHIAFBBHUhBiAPQX9qIQlBACAOayEFIAYgACAJIAUgCBBDIAkgDWshBCAGIAAgBCAFIAgQQyABQQV1IQtBACAGayEGIAsgACAJIAYgCEEQEEQgCSAOayEFIAsgACAFIAYgCEEQEEQgDkEBdCEFIAkgBWshBSALIAAgBSAGIAhBEBBEIA5BfWwhBSAJIAVqIQUgCyAAIAUgBiAIQRAQRCAHQXxqIQYgBkEBdSEOIAdBCUoEQEECIQUDQCAFQQJqIQYgASAGdSEEIAVBAWohBkECIAV0IQogCkEASgRAIAEgBUEEanUhEEEAIARBAXVrIRJBCCAFdCETQQAhBQNAIAUgBGwhESAJIBFrIREgECAAIBEgEiAIIBMQRCAFQQFqIQUgBSAKRw0ACwsgBiAOSARAIAYhBQwBCwsFQQIhBgsgB0F5aiEOIAYgDkgEQANAIAZBAmohBSABIAV1IRBBCCAGdCESIAZBBmohBSABIAV1IQcgBkEBaiEEQQIgBnQhEyAHQQBKBEBBACAQQQF1ayERIBJBAnQhGCAIIQYgCSEFA0AgEyAAIAUgESAGIBIgEBBFIAYgGEECdGohBiAFQXhqIQUgB0F/aiEKIAdBAUoEQCAKIQcMAQsLCyAEIA5HBEAgBCEGDAELCwsgCyAAIAkgCCABEEYgDUF8aiEIIAwgCEECdGohBiAPQXxqIQkgBiAMTwRAIAwgCUECdGohCCACQcAIaiADQQJ0aiEFIAUoAgAhBQNAIAUvAQAhByAHQf//A3EhByAAIAdBAnRqIQQgBCgCACEEIAhBDGohCiAKIAQ2AgAgB0EBaiEEIAAgBEECdGohBCAEKAIAIQQgCEEIaiEKIAogBDYCACAHQQJqIQQgACAEQQJ0aiEEIAQoAgAhBCAGQQxqIQogCiAENgIAIAdBA2ohByAAIAdBAnRqIQcgBygCACEHIAZBCGohBCAEIAc2AgAgBUECaiEHIAcvAQAhByAHQf//A3EhByAAIAdBAnRqIQQgBCgCACEEIAhBBGohCiAKIAQ2AgAgB0EBaiEEIAAgBEECdGohBCAEKAIAIQQgCCAENgIAIAdBAmohBCAAIARBAnRqIQQgBCgCACEEIAZBBGohCiAKIAQ2AgAgB0EDaiEHIAAgB0ECdGohByAHKAIAIQcgBiAHNgIAIAZBcGohBiAIQXBqIQggBUEEaiEFIAYgDE8NAAsLIAwgD0ECdGoiB0FwaiEIIAggDEsEQCACQbAIaiADQQJ0aiEGIAwhBSAGKAIAIQQgByEGA0AgBSoCACEZIAZBeGohCiAKKgIAIRogGSAakyEbIAVBBGohCyALKgIAIRwgBkF8aiENIA0qAgAhHSAcIB2SIR4gBEEEaiEOIA4qAgAhICAbICCUIR8gBCoCACEhIB4gIZQhIiAfICKSIR8gICAelCEeIBsgIZQhGyAeIBuTIRsgGSAakiEZIBwgHZMhGiAZIB+SIRwgBSAcOAIAIBogG5IhHCALIBw4AgAgGSAfkyEZIAogGTgCACAbIBqTIRkgDSAZOAIAIAVBCGohCiAKKgIAIRkgCCoCACEaIBkgGpMhGyAFQQxqIQsgCyoCACEcIAZBdGohBiAGKgIAIR0gHCAdkiEeIARBDGohDSANKgIAISAgGyAglCEfIARBCGohDSANKgIAISEgHiAhlCEiIB8gIpIhHyAgIB6UIR4gGyAhlCEbIB4gG5MhGyAZIBqSIRkgHCAdkyEaIBkgH5IhHCAKIBw4AgAgGiAbkiEcIAsgHDgCACAZIB+TIRkgCCAZOAIAIBsgGpMhGSAGIBk4AgAgBEEQaiEKIAVBEGohBSAIQXBqIQQgBSAESQRAIAghBiAEIQggCiEEDAELCwsgB0FgaiEIIAggDE8EQCACQagIaiADQQJ0aiECIAIoAgAhAiACIA9BAnRqIQIgAUF8aiEBIAAgAUECdGohAyAIIQEgFSEIIAAgCUECdGohBSAAIQYgByEAA0AgAkFgaiEHIABBeGohBCAEKgIAIRkgAkF8aiEEIAQqAgAhGiAZIBqUIR0gAEF8aiEEIAQqAgAhGyACQXhqIQQgBCoCACEcIBsgHJQhHiAdIB6TIR0gGSAclCEZIBmMIRkgGiAblCEaIBkgGpMhGSAGIB04AgAgHYwhGiAFQQxqIQQgBCAaOAIAIAggGTgCACADQQxqIQQgBCAZOAIAIABBcGohBCAEKgIAIRkgAkF0aiEEIAQqAgAhGiAZIBqUIR0gAEF0aiEEIAQqAgAhGyACQXBqIQQgBCoCACEcIBsgHJQhHiAdIB6TIR0gGSAclCEZIBmMIRkgGiAblCEaIBkgGpMhGSAGQQRqIQQgBCAdOAIAIB2MIRogBUEIaiEEIAQgGjgCACAIQQRqIQQgBCAZOAIAIANBCGohBCAEIBk4AgAgAEFoaiEEIAQqAgAhGSACQWxqIQQgBCoCACEaIBkgGpQhHSAAQWxqIQQgBCoCACEbIAJBaGohBCAEKgIAIRwgGyAclCEeIB0gHpMhHSAZIByUIRkgGYwhGSAaIBuUIRogGSAakyEZIAZBCGohBCAEIB04AgAgHYwhGiAFQQRqIQQgBCAaOAIAIAhBCGohBCAEIBk4AgAgA0EEaiEEIAQgGTgCACABKgIAIRkgAkFkaiECIAIqAgAhGiAZIBqUIR0gAEFkaiEAIAAqAgAhGyAHKgIAIRwgGyAclCEeIB0gHpMhHSAZIByUIRkgGYwhGSAaIBuUIRogGSAakyEZIAZBDGohACAAIB04AgAgHYwhGiAFIBo4AgAgCEEMaiEAIAAgGTgCACADIBk4AgAgBkEQaiEGIAhBEGohCCAFQXBqIQUgA0FwaiEDIAFBYGohAiACIAxPBEAgASEAIAIhASAHIQIMAQsLCyAUIBc2AgAgFiQGC8UBAQF/IABBAXYhASABQdWq1aoFcSEBIABBAXQhACAAQarVqtV6cSEAIAEgAHIhACAAQQJ2IQEgAUGz5syZA3EhASAAQQJ0IQAgAEHMmbPmfHEhACABIAByIQAgAEEEdiEBIAFBj568+ABxIQEgAEEEdCEAIABB8OHDh39xIQAgASAAciEAIABBCHYhASABQf+B/AdxIQEgAEEIdCEAIABBgP6DeHEhACABIAByIQAgAEEQdiEBIABBEHQhACABIAByIQAgAAtBAQN/IAFBAEoEQCAAIAFBAnRqIQQDQCAAIANBAnRqIQUgBSAENgIAIAQgAmohBCADQQFqIQMgAyABRw0ACwsgAAtrAQN/IAFBA2ohASABQXxxIQEgAEHEAGohAiACKAIAIQIgAgR/IABB0ABqIQMgAygCACEEIAQgAWshASAAQcwAaiEAIAAoAgAhACABIABIBH9BAAUgAyABNgIAIAIgAWoLBSABEF4LIQAgAAvaBgIPfwJ9IAFBFWohDCAMLAAAIQwCfyAMBH8gBSgCACEJIAQoAgAhCgJAIAdBAEoEfyAAQegKaiEOIABB5ApqIRAgAUEIaiETIAFBF2ohFCABQawQaiEVIAYgA2whESABQRZqIRYgAUEcaiESIAchDCAKIQYgASgCACEKIAkhBwJAAkADQAJAIA4oAgAhCSAJQQpIBEAgABA0CyAQKAIAIQsgC0H/B3EhCSABQSRqIAlBAXRqIQkgCS4BACEJIAlBf0oEQCATKAIAIQggCCAJaiEIIAgtAAAhCCAIQf8BcSEIIAsgCHYhCyAQIAs2AgAgDigCACELIAsgCGshCyALQQBIIQhBACALIAgbIQ1BfyAJIAgbIQsgDiANNgIABSAAIAEQNSELCyAULAAAIQkgCQRAIBUoAgAhCSALIAlODQMLIAtBAEgNACAHIANsIQkgCiAJaiEIIAggBmohCCAIIBFKIQggESAJayEJIAkgBmohCSAJIAogCBshCSABKAIAIQogCiALbCELIBYsAAAhCCAJQQBKIQogCARAIAoEQCASKAIAIQ1DAAAAACEXQQAhCgNAIAogC2ohCCANIAhBAnRqIQggCCoCACEYIBcgGJIhFyACIAZBAnRqIQggCCgCACEIIAhFIQ8gCCAHQQJ0aiEIIA9FBEAgCCoCACEYIBcgGJIhGCAIIBg4AgALIAZBAWohBiAGIANGIQggByAIaiEHQQAgBiAIGyEGIApBAWohCiAKIAlHDQALCwUgCgRAQQAhCgNAIAIgBkECdGohCCAIKAIAIQggCARAIBIoAgAhDSAKIAtqIQ8gDSAPQQJ0aiENIA0qAgAhFyAXQwAAAACSIRcgCCAHQQJ0aiEIIAgqAgAhGCAYIBeSIRcgCCAXOAIACyAGQQFqIQYgBiADRiEIIAcgCGohB0EAIAYgCBshBiAKQQFqIQogCiAJRw0ACwsLIAwgCWshDCAMQQBMDQUgCSEKDAELCwwBC0GnFUHEE0GgDkHLFRAECyAAQdQKaiEBIAEsAAAhASABRQRAIABB3ApqIQEgASgCACEBQQAgAQ0EGgsgAEEVEBVBAAwDBSAJIQcgCgshBgsgBCAGNgIAIAUgBzYCAEEBBSAAQRUQFUEACwshACAAC+ABAQJ/AkAgBQRAIARBAEoEQEEAIQUDQCACIANBAnRqIQYgBCAFayEHIAAgASAGIAcQQCEGIAZFBEBBACEADAQLIAEoAgAhBiAGIAVqIQUgBiADaiEDIAUgBEgNAAtBASEABUEBIQALBSABKAIAIQUgBCAFbSEFIAIgA0ECdGohBiAFQQBKBEAgBCADayEDQQAhAgNAIAYgAkECdGohBCADIAJrIQcgACABIAQgByAFED8hBCAERSEEIAQEQEEAIQAMBAsgAkEBaiECIAIgBUgNAAtBASEABUEBIQALCwsgAAu+AQIDfwN9IAAgARBBIQUgBUEASARAQQAhAAUgASgCACEAIAAgA0ghBiAAIAMgBhshAyAAIAVsIQUgA0EASgRAIAEoAhwhBiABLAAWRSEHQQAhAANAIAAgBWohASAGIAFBAnRqIQEgASoCACEIIAkgCJIhCCAAIARsIQEgAiABQQJ0aiEBIAEqAgAhCiAKIAiSIQogASAKOAIAIAkgCCAHGyEJIABBAWohACAAIANIDQALQQEhAAVBASEACwsgAAvFAgIDfwJ9IAAgARBBIQUCQCAFQQBIBEBBACEABSABKAIAIQAgACADSCEEIAAgAyAEGyEDIAAgBWwhBSABQRZqIQAgACwAACEEIANBAEohACAEBEAgAEUEQEEBIQAMAwsgASgCHCEEIAFBDGohBkEAIQADQCAAIAVqIQEgBCABQQJ0aiEBIAEqAgAhCCAHIAiSIQcgAiAAQQJ0aiEBIAEqAgAhCCAIIAeSIQggASAIOAIAIAYqAgAhCCAHIAiSIQcgAEEBaiEAIAAgA0gNAAtBASEABSAARQRAQQEhAAwDCyABKAIcIQRBACEAA0AgACAFaiEBIAQgAUECdGohASABKgIAIQcgB0MAAAAAkiEHIAIgAEECdGohASABKgIAIQggCCAHkiEHIAEgBzgCACAAQQFqIQAgACADSA0AC0EBIQALCwsgAAvMAgEFfyABQRVqIQIgAiwAACECAkAgAgRAIABB6ApqIQUgBSgCACECIAJBCkgEQCAAEDQLIABB5ApqIQQgBCgCACEGIAZB/wdxIQIgAUEkaiACQQF0aiECIAIuAQAhAiACQX9KBEAgAUEIaiEDIAMoAgAhAyADIAJqIQMgAy0AACEDIANB/wFxIQMgBiADdiEGIAQgBjYCACAFKAIAIQQgBCADayEEIARBAEghBkEAIAQgBhshBEF/IAIgBhshAiAFIAQ2AgAFIAAgARA1IQILIAFBF2ohBSAFLAAAIQUgBQRAIAFBrBBqIQEgASgCACEBIAIgAU4EQEHvFUHEE0HCDUGFFhAECwsgAkEASARAIABB1ApqIQEgASwAACEBIAFFBEAgAEHcCmohASABKAIAIQEgAQ0DCyAAQRUQFQsFIABBFRAVQX8hAgsLIAILtAICBX8CfSAEIAJrIQQgAyABayEIIARBf0ohBkEAIARrIQcgBCAHIAYbIQcgBCAIbSEGIARBH3UhBCAEQQFyIQogBkF/SiEEQQAgBmshCSAGIAkgBBshBCAEIAhsIQQgByAEayEHIAMgBUohBCAFIAMgBBshBCAEIAFKBEAgAkECdEGgCGohAyADKgIAIQsgACABQQJ0aiEDIAMqAgAhDCALIAyUIQsgAyALOAIAIAFBAWohASABIARIBEBBACEDA0AgAyAHaiEDIAMgCEghBUEAIAogBRshCUEAIAggBRshBSADIAVrIQMgAiAGaiAJaiECIAJBAnRBoAhqIQUgBSoCACELIAAgAUECdGohBSAFKgIAIQwgCyAMlCELIAUgCzgCACABQQFqIQEgASAESA0ACwsLC4sHAgR/Bn0gASACQQJ0aiEBIABBA3EhAiACBEBBmxZBxBNB4BJBqBYQBAsgAEEDSgRAIABBAnYhACABIANBAnRqIQMDQCABKgIAIQsgAyoCACEMIAsgDJMhDSABQXxqIQIgAioCACEKIANBfGohBSAFKgIAIQkgCiAJkyEOIAsgDJIhCSABIAk4AgAgBSoCACEJIAogCZIhCSACIAk4AgAgBCoCACEJIA0gCZQhCiAEQQRqIQIgAioCACEJIA4gCZQhCSAKIAmTIQkgAyAJOAIAIAQqAgAhCSAOIAmUIQogAioCACEJIA0gCZQhCSAKIAmSIQkgBSAJOAIAIARBIGohByABQXhqIQggCCoCACELIANBeGohBSAFKgIAIQwgCyAMkyENIAFBdGohAiACKgIAIQogA0F0aiEGIAYqAgAhCSAKIAmTIQ4gCyAMkiEJIAggCTgCACAGKgIAIQkgCiAJkiEJIAIgCTgCACAHKgIAIQkgDSAJlCEKIARBJGohAiACKgIAIQkgDiAJlCEJIAogCZMhCSAFIAk4AgAgByoCACEJIA4gCZQhCiACKgIAIQkgDSAJlCEJIAogCZIhCSAGIAk4AgAgBEFAayEHIAFBcGohCCAIKgIAIQsgA0FwaiEFIAUqAgAhDCALIAyTIQ0gAUFsaiECIAIqAgAhCiADQWxqIQYgBioCACEJIAogCZMhDiALIAySIQkgCCAJOAIAIAYqAgAhCSAKIAmSIQkgAiAJOAIAIAcqAgAhCSANIAmUIQogBEHEAGohAiACKgIAIQkgDiAJlCEJIAogCZMhCSAFIAk4AgAgByoCACEJIA4gCZQhCiACKgIAIQkgDSAJlCEJIAogCZIhCSAGIAk4AgAgBEHgAGohByABQWhqIQggCCoCACELIANBaGohBSAFKgIAIQwgCyAMkyENIAFBZGohAiACKgIAIQogA0FkaiEGIAYqAgAhCSAKIAmTIQ4gCyAMkiEJIAggCTgCACAGKgIAIQkgCiAJkiEJIAIgCTgCACAHKgIAIQkgDSAJlCEKIARB5ABqIQIgAioCACEJIA4gCZQhCSAKIAmTIQkgBSAJOAIAIAcqAgAhCSAOIAmUIQogAioCACEJIA0gCZQhCSAKIAmSIQkgBiAJOAIAIARBgAFqIQQgAUFgaiEBIANBYGohAyAAQX9qIQIgAEEBSgRAIAIhAAwBCwsLC4EHAgN/BX0gASACQQJ0aiEBIABBA0oEQCAAQQJ2IQYgASADQQJ0aiECIAEhACAGIQEDQCAAKgIAIQkgAioCACEKIAkgCpMhDCAAQXxqIQYgBioCACENIAJBfGohAyADKgIAIQsgDSALkyELIAkgCpIhCSAAIAk4AgAgAyoCACEJIA0gCZIhCSAGIAk4AgAgBCoCACEJIAwgCZQhCSAEQQRqIQYgBioCACEKIAsgCpQhCiAJIAqTIQkgAiAJOAIAIAQqAgAhCSALIAmUIQkgBioCACEKIAwgCpQhCiAJIAqSIQkgAyAJOAIAIAQgBUECdGohAyAAQXhqIQYgBioCACEJIAJBeGohByAHKgIAIQogCSAKkyEMIABBdGohCCAIKgIAIQ0gAkF0aiEEIAQqAgAhCyANIAuTIQsgCSAKkiEJIAYgCTgCACAEKgIAIQkgDSAJkiEJIAggCTgCACADKgIAIQkgDCAJlCEJIANBBGohBiAGKgIAIQogCyAKlCEKIAkgCpMhCSAHIAk4AgAgAyoCACEJIAsgCZQhCSAGKgIAIQogDCAKlCEKIAkgCpIhCSAEIAk4AgAgAyAFQQJ0aiEDIABBcGohBiAGKgIAIQkgAkFwaiEHIAcqAgAhCiAJIAqTIQwgAEFsaiEIIAgqAgAhDSACQWxqIQQgBCoCACELIA0gC5MhCyAJIAqSIQkgBiAJOAIAIAQqAgAhCSANIAmSIQkgCCAJOAIAIAMqAgAhCSAMIAmUIQkgA0EEaiEGIAYqAgAhCiALIAqUIQogCSAKkyEJIAcgCTgCACADKgIAIQkgCyAJlCEJIAYqAgAhCiAMIAqUIQogCSAKkiEJIAQgCTgCACADIAVBAnRqIQMgAEFoaiEGIAYqAgAhCSACQWhqIQcgByoCACEKIAkgCpMhDCAAQWRqIQggCCoCACENIAJBZGohBCAEKgIAIQsgDSALkyELIAkgCpIhCSAGIAk4AgAgBCoCACEJIA0gCZIhCSAIIAk4AgAgAyoCACEJIAwgCZQhCSADQQRqIQYgBioCACEKIAsgCpQhCiAJIAqTIQkgByAJOAIAIAMqAgAhCSALIAmUIQkgBioCACEKIAwgCpQhCiAJIAqSIQkgBCAJOAIAIABBYGohACACQWBqIQIgAyAFQQJ0aiEEIAFBf2ohAyABQQFKBEAgAyEBDAELCwsL6QYCAn8OfSAEKgIAIQ8gBEEEaiEHIAcqAgAhECAEIAVBAnRqIQcgByoCACERIAVBAWohByAEIAdBAnRqIQcgByoCACESIAVBAXQhCCAEIAhBAnRqIQcgByoCACETIAhBAXIhByAEIAdBAnRqIQcgByoCACEUIAVBA2whByAEIAdBAnRqIQUgBSoCACEVIAdBAWohBSAEIAVBAnRqIQQgBCoCACEWIAEgAkECdGohASAAQQBKBEBBACAGayEGIAEgA0ECdGohAwNAIAEqAgAhCyADKgIAIQwgCyAMkyENIAFBfGohAiACKgIAIQogA0F8aiEEIAQqAgAhCSAKIAmTIQ4gCyAMkiEJIAEgCTgCACAEKgIAIQkgCiAJkiEJIAIgCTgCACAPIA2UIQogECAOlCEJIAogCZMhCSADIAk4AgAgDyAOlCEKIBAgDZQhCSAJIAqSIQkgBCAJOAIAIAFBeGohBSAFKgIAIQsgA0F4aiEEIAQqAgAhDCALIAyTIQ0gAUF0aiECIAIqAgAhCiADQXRqIQcgByoCACEJIAogCZMhDiALIAySIQkgBSAJOAIAIAcqAgAhCSAKIAmSIQkgAiAJOAIAIBEgDZQhCiASIA6UIQkgCiAJkyEJIAQgCTgCACARIA6UIQogEiANlCEJIAkgCpIhCSAHIAk4AgAgAUFwaiEFIAUqAgAhCyADQXBqIQQgBCoCACEMIAsgDJMhDSABQWxqIQIgAioCACEKIANBbGohByAHKgIAIQkgCiAJkyEOIAsgDJIhCSAFIAk4AgAgByoCACEJIAogCZIhCSACIAk4AgAgEyANlCEKIBQgDpQhCSAKIAmTIQkgBCAJOAIAIBMgDpQhCiAUIA2UIQkgCSAKkiEJIAcgCTgCACABQWhqIQUgBSoCACELIANBaGohBCAEKgIAIQwgCyAMkyENIAFBZGohAiACKgIAIQogA0FkaiEHIAcqAgAhCSAKIAmTIQ4gCyAMkiEJIAUgCTgCACAHKgIAIQkgCiAJkiEJIAIgCTgCACAVIA2UIQogFiAOlCEJIAogCZMhCSAEIAk4AgAgFSAOlCEKIBYgDZQhCSAJIAqSIQkgByAJOAIAIAEgBkECdGohASADIAZBAnRqIQMgAEF/aiECIABBAUoEQCACIQAMAQsLCwvWBAICfwd9IARBA3UhBCADIARBAnRqIQMgAyoCACENIAEgAkECdGohASAAQQR0IQBBACAAayEAIAEgAEECdGohBiAAQQBIBEAgASEAA0AgACoCACEHIABBYGohASABKgIAIQggByAIkyELIABBfGohAiACKgIAIQkgAEFcaiEDIAMqAgAhCiAJIAqTIQwgByAIkiEHIAAgBzgCACAJIAqSIQcgAiAHOAIAIAEgCzgCACADIAw4AgAgAEF4aiECIAIqAgAhByAAQVhqIQMgAyoCACEIIAcgCJMhCSAAQXRqIQQgBCoCACEKIABBVGohBSAFKgIAIQsgCiALkyEMIAcgCJIhByACIAc4AgAgCiALkiEHIAQgBzgCACAJIAySIQcgDSAHlCEHIAMgBzgCACAMIAmTIQcgDSAHlCEHIAUgBzgCACAAQVBqIQIgAioCACEHIABBcGohAyADKgIAIQggByAIkyELIABBbGohBCAEKgIAIQkgAEFMaiEFIAUqAgAhCiAJIAqTIQwgByAIkiEHIAMgBzgCACAJIAqSIQcgBCAHOAIAIAIgDDgCACAFIAs4AgAgAEFIaiECIAIqAgAhByAAQWhqIQMgAyoCACEIIAcgCJMhCSAAQWRqIQQgBCoCACEKIABBRGohBSAFKgIAIQsgCiALkyEMIAcgCJIhByADIAc4AgAgCiALkiEHIAQgBzgCACAJIAySIQcgDSAHlCEHIAIgBzgCACAJIAyTIQcgDSAHlCEHIAUgBzgCACAAEEcgARBHIABBQGohACAAIAZLDQALCwuXAgIEfwZ9IAAqAgAhBSAAQXBqIQEgASoCACEIIAUgCJMhBiAFIAiSIQUgAEF4aiECIAIqAgAhCCAAQWhqIQMgAyoCACEHIAggB5IhCSAIIAeTIQggBSAJkiEHIAAgBzgCACAFIAmTIQUgAiAFOAIAIABBdGohAiACKgIAIQUgAEFkaiEEIAQqAgAhByAFIAeTIQkgBiAJkiEKIAEgCjgCACAGIAmTIQYgAyAGOAIAIABBfGohASABKgIAIQYgAEFsaiEAIAAqAgAhCSAGIAmTIQogBiAJkiEGIAUgB5IhBSAFIAaSIQcgASAHOAIAIAYgBZMhBSACIAU4AgAgCiAIkyEFIAAgBTgCACAIIAqSIQUgBCAFOAIAC2IBAn8gAUEBdCEBIABB5ABqIQIgAigCACECIAEgAkYEQCAAQbgIaiEDBSAAQegAaiECIAIoAgAhAiABIAJGBEAgAEG8CGohAwVBvxZBxBNB6xdBwRYQBAsLIAMoAgAhACAACxQAIABBkhdBBhBkIQAgAEUhACAAC6oBAQN/IABB2ApqIQEgASgCACEDAn8CQCADQX9HDQAgAEHTCmohAwNAAkAgABAxIQJBACACRQ0DGiADLAAAIQIgAkEBcSECIAINACABKAIAIQIgAkF/Rg0BDAILCyAAQSAQFUEADAELIABB3ApqIQEgAUEANgIAIABB6ApqIQEgAUEANgIAIABB7ApqIQEgAUEANgIAIABB1ApqIQAgAEEAOgAAQQELIQAgAAtFAQJ/IABBFGohAiACKAIAIQMgAyABaiEBIAIgATYCACAAQRxqIQIgAigCACECIAEgAk8EQCAAQdQAaiEAIABBATYCAAsLagEEfwNAQQAhACACQRh0IQEDQCABQQF0IQMgAUEfdSEBIAFBt7uEJnEhASABIANzIQEgAEEBaiEAIABBCEcNAAsgAkECdEHQGWohACAAIAE2AgAgAkEBaiEAIABBgAJHBEAgACECDAELCwuTAQEDfyABQQNqIQEgAUF8cSEBIABBCGohAiACKAIAIQMgAyABaiEDIAIgAzYCACAAQcQAaiECIAIoAgAhAiACBEAgAEHMAGohAyADKAIAIQQgBCABaiEBIABB0ABqIQAgACgCACEAIAEgAEoEQEEAIQAFIAIgBGohACADIAE2AgALBSABBH8gARBeBUEACyEACyAAC0gBAX8gAEHEAGohAyADKAIAIQMgAwRAIAJBA2ohASABQXxxIQEgAEHQAGohACAAKAIAIQIgAiABaiEBIAAgATYCAAUgARBfCwvGBQELfyMGIQ0jBkGAAWokBiANIgdCADcDACAHQgA3AwggB0IANwMQIAdCADcDGCAHQgA3AyAgB0IANwMoIAdCADcDMCAHQgA3AzggB0FAa0IANwMAIAdCADcDSCAHQgA3A1AgB0IANwNYIAdCADcDYCAHQgA3A2ggB0IANwNwIAdCADcDeAJAIAJBAEoEQANAIAEgBmohBCAELAAAIQQgBEF/Rw0CIAZBAWohBiAGIAJIDQALCwsCQCAGIAJGBEAgAEGsEGohACAAKAIAIQAgAARAQZgXQcQTQZ0IQa8XEAQFQQEhCwsFIAEgBmohBCAELQAAIQUgBUH/AXEhBSAAQQAgBkEAIAUgAxBXIAQsAAAhBCAEBEAgBEH/AXEhCkEBIQQDQEEgIARrIQVBASAFdCEFIAcgBEECdGohCCAIIAU2AgAgBEEBaiEFIAQgCkkEQCAFIQQMAQsLCyAGQQFqIQogCiACSARAQQEhBQJAAkACQAJAA0AgASAKaiEJIAksAAAhBiAGQX9GBEAgBSEGBSAGQf8BcSEIIAZFDQggCCEEA0ACQCAHIARBAnRqIQYgBigCACEMIAwNACAEQX9qIQYgBEEBTA0KIAYhBAwBCwsgBEEgTw0CIAZBADYCACAMEDohDiAFQQFqIQYgACAOIAogBSAIIAMQVyAJLQAAIQggCEH/AXEhBSAEIAVHBEAgCEH/AXFBIE4NBCAEIAVIBEADQCAHIAVBAnRqIQggCCgCACEJIAkNB0EgIAVrIQlBASAJdCEJIAkgDGohCSAIIAk2AgAgBUF/aiEFIAUgBEoNAAsLCwsgCkEBaiEKIAogAkgEQCAGIQUMAQVBASELDAgLAAALAAtBwRdBxBNBtAhBrxcQBAwCC0HSF0HEE0G5CEGvFxAEDAELQe0XQcQTQbsIQa8XEAQLBUEBIQsLCwsgDSQGIAsLtQYBEH8gAEEXaiEKIAosAAAhBCAEBEAgAEGsEGohCCAIKAIAIQMgA0EASgRAIAAoAiAhBiAAQaQQaigCACEFQQAhBANAIAYgBEECdGohAyADKAIAIQMgAxA6IQMgBSAEQQJ0aiEHIAcgAzYCACAEQQFqIQQgCCgCACEDIAQgA0gNAAsLBSAAQQRqIQcgBygCACEEIARBAEoEQCAAQSBqIQsgAEGkEGohDEEAIQQDQCABIAZqIQUgBSwAACEFIAAgBRBYIQUgBQRAIAsoAgAhBSAFIAZBAnRqIQUgBSgCACEFIAUQOiENIAwoAgAhDiAEQQFqIQUgDiAEQQJ0aiEEIAQgDTYCACAFIQQLIAZBAWohBiAHKAIAIQUgBiAFSA0ACwVBACEECyAAQawQaiEGIAYoAgAhBSAEIAVGBEAgBiEIIAQhAwVB/xdBxBNB/ghBlhgQBAsLIABBpBBqIQUgBSgCACEEIAQgA0EEQQIQZiAFKAIAIQQgCCgCACEDIAQgA0ECdGohBCAEQX82AgAgCiwAACEDIANFIQQgAEEEaiEGIAYgCCAEGyEEIAQoAgAhCwJAIAtBAEoEQCAAQSBqIREgAEGoEGohDCAAQQhqIRJBACEEA0ACQCADQf8BcQR/IAIgBEECdGohAyADKAIABSAECyEDIAEgA2osAAAhDSAAIA0QWCEDIAMEQCARKAIAIQMgAyAEQQJ0aiEDIAMoAgAhAyADEDohDiAIKAIAIQMgBSgCACEPIANBAUoEQEEAIQYDQCADQQF2IQcgByAGaiEQIA8gEEECdGohCSAJKAIAIQkgCSAOSyEJIAMgB2shAyAGIBAgCRshBiAHIAMgCRshAyADQQFKDQALBUEAIQYLIA8gBkECdGohAyADKAIAIQMgAyAORw0BIAosAAAhAyADBEAgAiAEQQJ0aiEDIAMoAgAhAyAMKAIAIQcgByAGQQJ0aiEHIAcgAzYCACASKAIAIQMgAyAGaiEDIAMgDToAAAUgDCgCACEDIAMgBkECdGohAyADIAQ2AgALCyAEQQFqIQQgBCALTg0DIAosAAAhAwwBCwtBrRhBxBNBnAlBlhgQBAsLC7cCAQp/IABBJGohASABQX9BgBAQehogAEEXaiEBIAEsAAAhASABRSEEIABBrBBqIQEgAEEEaiECIAIgASAEGyEBIAEoAgAhASABQf//AUghAiABQf//ASACGyEGIAFBAEoEQCAAQQhqIQEgAEEgaiEHIABBpBBqIQggASgCACEJQQAhAgNAIAkgAmohBSAFLQAAIQEgAUH/AXFBC0gEQCAEBH8gBygCACEBIAEgAkECdGohASABKAIABSAIKAIAIQEgASACQQJ0aiEBIAEoAgAhASABEDoLIQEgAUGACEkEQCACQf//A3EhCgNAIABBJGogAUEBdGohAyADIAo7AQAgBS0AACEDIANB/wFxIQNBASADdCEDIAMgAWohASABQYAISQ0ACwsLIAJBAWohAiACIAZIDQALCwtcAwJ/AX0CfCAAQf///wBxIQIgAEEVdiEBIAFB/wdxIQEgAEEASCEAIAK4IQQgBJohBSAFIAQgABshBCAEtiEDIAO7IQQgAUHseWohACAEIAAQcSEEIAS2IQMgAwviAQMBfwJ9A3wgALIhAyADuyEFIAUQdiEFIAW2IQMgAbIhBCADIASVIQMgA7shBSAFEHUhBSAFnCEFIAWqIQIgArIhAyADQwAAgD+SIQMgA7shBiABtyEFIAYgBRB3IQYgBpwhBiAGqiEBIAEgAEwhASABIAJqIQEgAbIhAyADQwAAgD+SIQQgBLshBiAGIAUQdyEGIAC3IQcgBiAHZEUEQEHrGEHEE0G1CUGLGRAECyADuyEGIAYgBRB3IQUgBZwhBSAFqiECIAIgAEoEQEGaGUHEE0G2CUGLGRAEBSABDwtBAAs/AQF/IAAvAQAhACABLwEAIQEgAEH//wNxIAFB//8DcUghAiAAQf//A3EgAUH//wNxSiEAQX8gACACGyEAIAALigEBB38gAUEASgRAIAAgAUEBdGohCEGAgAQhCUF/IQoDQCAAIARBAXRqIQUgBS8BACEGIAYhBSAKIAVIBEAgCC8BACEHIAYgB0gEQCACIAQ2AgAgBSEKCwsgCSAFSgRAIAgvAQAhByAGIAdKBEAgAyAENgIAIAUhCQsLIARBAWohBCAEIAFHDQALCwumAgEHfyACQQF2IQMgAkF8cSEEIAJBA3UhCCADQQJ0IQMgACADEE0hBSAAQaAIaiABQQJ0aiEGIAYgBTYCACAAIAMQTSEHIABBqAhqIAFBAnRqIQUgBSAHNgIAIAAgBBBNIQQgAEGwCGogAUECdGohByAHIAQ2AgAgBigCACEGAn8CQCAGRQ0AIAUoAgAhBSAFRSEHIARFIQkgCSAHcg0AIAIgBiAFIAQQWiAAIAMQTSEDIABBuAhqIAFBAnRqIQQgBCADNgIAIANFBEAgAEEDEBVBAAwCCyACIAMQWyAIQQF0IQMgACADEE0hAyAAQcAIaiABQQJ0aiEBIAEgAzYCACADBH8gAiADEFxBAQUgAEEDEBVBAAsMAQsgAEEDEBVBAAshACAAC28BAn8gAEEXaiEGIAYsAAAhByAAKAIgIQYgBwR/IAYgA0ECdGohBiAGIAE2AgAgBEH/AXEhASAAQQhqIQAgACgCACEAIAAgA2ohACAAIAE6AAAgAiEBIAUgA0ECdGoFIAYgAkECdGoLIgAgATYCAAtZAQF/IABBF2ohACAALAAAIQIgAUH/AXFB/wFGIQAgAkUEQCABQf8BcUEKSiEBIAAgAXMhACAAQQFxIQAgAA8LIAAEQEHMGEHEE0HqCEHbGBAEBUEBDwtBAAsrAQF/IAAoAgAhACABKAIAIQEgACABSSECIAAgAUshAEF/IAAgAhshACAAC6YDAwZ/AX0DfCAAQQJ1IQggAEEDdSEJIABBA0oEQCAAtyENA0AgBkECdCEEIAS3IQsgC0QYLURU+yEJQKIhCyALIA2jIQwgDBBzIQsgC7YhCiABIAVBAnRqIQQgBCAKOAIAIAwQdCELIAu2IQogCowhCiAFQQFyIQcgASAHQQJ0aiEEIAQgCjgCACAHtyELIAtEGC1EVPshCUCiIQsgCyANoyELIAtEAAAAAAAA4D+iIQwgDBBzIQsgC7YhCiAKQwAAAD+UIQogAiAFQQJ0aiEEIAQgCjgCACAMEHQhCyALtiEKIApDAAAAP5QhCiACIAdBAnRqIQQgBCAKOAIAIAZBAWohBiAFQQJqIQUgBiAISA0ACyAAQQdKBEAgALchDEEAIQFBACEAA0AgAEEBciEFIAVBAXQhAiACtyELIAtEGC1EVPshCUCiIQsgCyAMoyENIA0QcyELIAu2IQogAyAAQQJ0aiECIAIgCjgCACANEHQhCyALtiEKIAqMIQogAyAFQQJ0aiECIAIgCjgCACABQQFqIQEgAEECaiEAIAEgCUgNAAsLCwunAQMCfwF9AnwgAEEBdSECIABBAUoEQCACtyEGQQAhAANAIAC3IQUgBUQAAAAAAADgP6AhBSAFIAajIQUgBUQAAAAAAADgP6IhBSAFRBgtRFT7IQlAoiEFIAUQdCEFIAW2IQQgBBBdIQQgBLshBSAFRBgtRFT7Ifk/oiEFIAUQdCEFIAW2IQQgASAAQQJ0aiEDIAMgBDgCACAAQQFqIQAgACACSA0ACwsLXwEEfyAAQQN1IQMgAEEHSgRAQSQgABAtayEEQQAhAANAIAAQOiECIAIgBHYhAiACQQJ0IQIgAkH//wNxIQIgASAAQQF0aiEFIAUgAjsBACAAQQFqIQAgACADSA0ACwsLDQEBfSAAIACUIQEgAQvyOgEXfwJAAkAjBiEOIwZBEGokBiAOIRcCfyAAQfUBSQR/QdAhKAIAIgdBECAAQQtqQXhxIABBC0kbIgJBA3YiAHYiA0EDcQRAIANBAXFBAXMgAGoiAUEDdEH4IWoiAkEIaiIEKAIAIgBBCGoiBigCACIDIAJGBEBB0CEgB0EBIAF0QX9zcTYCAAVB4CEoAgAgA0sEQBAGCyADQQxqIgUoAgAgAEYEQCAFIAI2AgAgBCADNgIABRAGCwsgACABQQN0IgNBA3I2AgQgACADakEEaiIAIAAoAgBBAXI2AgAgDiQGIAYPCyACQdghKAIAIg1LBH8gAwRAIAMgAHRBAiAAdCIAQQAgAGtycSIAQQAgAGtxQX9qIgNBDHZBEHEhACADIAB2IgNBBXZBCHEiASAAciADIAF2IgBBAnZBBHEiA3IgACADdiIAQQF2QQJxIgNyIAAgA3YiAEEBdkEBcSIDciAAIAN2aiIBQQN0QfghaiIFQQhqIgkoAgAiAEEIaiIKKAIAIgMgBUYEQEHQISAHQQEgAXRBf3NxIgQ2AgAFQeAhKAIAIANLBEAQBgsgA0EMaiILKAIAIABGBEAgCyAFNgIAIAkgAzYCACAHIQQFEAYLCyAAIAJBA3I2AgQgACACaiIHIAFBA3QiAyACayIFQQFyNgIEIAAgA2ogBTYCACANBEBB5CEoAgAhAiANQQN2IgNBA3RB+CFqIQAgBEEBIAN0IgNxBEBB4CEoAgAgAEEIaiIDKAIAIgFLBEAQBgUgASEGIAMhDAsFQdAhIAQgA3I2AgAgACEGIABBCGohDAsgDCACNgIAIAYgAjYCDCACIAY2AgggAiAANgIMC0HYISAFNgIAQeQhIAc2AgAgDiQGIAoPC0HUISgCACIMBH8gDEEAIAxrcUF/aiIDQQx2QRBxIQAgAyAAdiIDQQV2QQhxIgQgAHIgAyAEdiIAQQJ2QQRxIgNyIAAgA3YiAEEBdkECcSIDciAAIAN2IgBBAXZBAXEiA3IgACADdmpBAnRBgCRqKAIAIgQhAyAEKAIEQXhxIAJrIQoDQAJAIAMoAhAiAEUEQCADKAIUIgBFDQELIAAhAyAAIAQgACgCBEF4cSACayIAIApJIgYbIQQgACAKIAYbIQoMAQsLQeAhKAIAIg8gBEsEQBAGCyAEIAJqIgggBE0EQBAGCyAEKAIYIQsCQCAEKAIMIgAgBEYEQCAEQRRqIgMoAgAiAEUEQCAEQRBqIgMoAgAiAEUNAgsDQAJAIABBFGoiBigCACIJRQRAIABBEGoiBigCACIJRQ0BCyAGIQMgCSEADAELCyAPIANLBEAQBgUgA0EANgIAIAAhAQsFIA8gBCgCCCIDSwRAEAYLIANBDGoiBigCACAERwRAEAYLIABBCGoiCSgCACAERgRAIAYgADYCACAJIAM2AgAgACEBBRAGCwsLAkAgCwRAIAQgBCgCHCIAQQJ0QYAkaiIDKAIARgRAIAMgATYCACABRQRAQdQhIAxBASAAdEF/c3E2AgAMAwsFQeAhKAIAIAtLBEAQBgUgC0EQaiIAIAtBFGogACgCACAERhsgATYCACABRQ0DCwtB4CEoAgAiAyABSwRAEAYLIAEgCzYCGCAEKAIQIgAEQCADIABLBEAQBgUgASAANgIQIAAgATYCGAsLIAQoAhQiAARAQeAhKAIAIABLBEAQBgUgASAANgIUIAAgATYCGAsLCwsgCkEQSQRAIAQgCiACaiIAQQNyNgIEIAQgAGpBBGoiACAAKAIAQQFyNgIABSAEIAJBA3I2AgQgCCAKQQFyNgIEIAggCmogCjYCACANBEBB5CEoAgAhAiANQQN2IgNBA3RB+CFqIQBBASADdCIDIAdxBEBB4CEoAgAgAEEIaiIDKAIAIgFLBEAQBgUgASEFIAMhEAsFQdAhIAMgB3I2AgAgACEFIABBCGohEAsgECACNgIAIAUgAjYCDCACIAU2AgggAiAANgIMC0HYISAKNgIAQeQhIAg2AgALIA4kBiAEQQhqDwUgAgsFIAILBSAAQb9/SwR/QX8FIABBC2oiAEF4cSEEQdQhKAIAIgYEfyAAQQh2IgAEfyAEQf///wdLBH9BHwUgBEEOIAAgAEGA/j9qQRB2QQhxIgB0IgFBgOAfakEQdkEEcSICIAByIAEgAnQiAEGAgA9qQRB2QQJxIgFyayAAIAF0QQ92aiIAQQdqdkEBcSAAQQF0cgsFQQALIRJBACAEayECAkACQCASQQJ0QYAkaigCACIABEBBACEBIARBAEEZIBJBAXZrIBJBH0YbdCEMA0AgACgCBEF4cSAEayIQIAJJBEAgEAR/IBAhAiAABSAAIQFBACECDAQLIQELIAUgACgCFCIFIAVFIAUgAEEQaiAMQR92QQJ0aigCACIARnIbIQUgDEEBdCEMIAANAAsgASEABUEAIQALIAUgAHJFBEAgBEECIBJ0IgBBACAAa3IgBnEiAEUNBhogAEEAIABrcUF/aiIFQQx2QRBxIQFBACEAIAUgAXYiBUEFdkEIcSIMIAFyIAUgDHYiAUECdkEEcSIFciABIAV2IgFBAXZBAnEiBXIgASAFdiIBQQF2QQFxIgVyIAEgBXZqQQJ0QYAkaigCACEFCyAFBH8gACEBIAUhAAwBBSAACyEFDAELIAEhBSACIQEDQCAAKAIEIQwgACgCECICRQRAIAAoAhQhAgsgDEF4cSAEayIQIAFJIQwgECABIAwbIQEgACAFIAwbIQUgAgR/IAIhAAwBBSABCyECCwsgBQR/IAJB2CEoAgAgBGtJBH9B4CEoAgAiESAFSwRAEAYLIAUgBGoiCCAFTQRAEAYLIAUoAhghDwJAIAUoAgwiACAFRgRAIAVBFGoiASgCACIARQRAIAVBEGoiASgCACIARQ0CCwNAAkAgAEEUaiIJKAIAIgtFBEAgAEEQaiIJKAIAIgtFDQELIAkhASALIQAMAQsLIBEgAUsEQBAGBSABQQA2AgAgACEHCwUgESAFKAIIIgFLBEAQBgsgAUEMaiIJKAIAIAVHBEAQBgsgAEEIaiILKAIAIAVGBEAgCSAANgIAIAsgATYCACAAIQcFEAYLCwsCQCAPBEAgBSAFKAIcIgBBAnRBgCRqIgEoAgBGBEAgASAHNgIAIAdFBEBB1CEgBkEBIAB0QX9zcSIDNgIADAMLBUHgISgCACAPSwRAEAYFIA9BEGoiACAPQRRqIAAoAgAgBUYbIAc2AgAgB0UEQCAGIQMMBAsLC0HgISgCACIBIAdLBEAQBgsgByAPNgIYIAUoAhAiAARAIAEgAEsEQBAGBSAHIAA2AhAgACAHNgIYCwsgBSgCFCIABEBB4CEoAgAgAEsEQBAGBSAHIAA2AhQgACAHNgIYIAYhAwsFIAYhAwsFIAYhAwsLAkAgAkEQSQRAIAUgAiAEaiIAQQNyNgIEIAUgAGpBBGoiACAAKAIAQQFyNgIABSAFIARBA3I2AgQgCCACQQFyNgIEIAggAmogAjYCACACQQN2IQEgAkGAAkkEQCABQQN0QfghaiEAQdAhKAIAIgNBASABdCIBcQRAQeAhKAIAIABBCGoiAygCACIBSwRAEAYFIAEhDSADIRMLBUHQISADIAFyNgIAIAAhDSAAQQhqIRMLIBMgCDYCACANIAg2AgwgCCANNgIIIAggADYCDAwCCyACQQh2IgAEfyACQf///wdLBH9BHwUgAkEOIAAgAEGA/j9qQRB2QQhxIgB0IgFBgOAfakEQdkEEcSIEIAByIAEgBHQiAEGAgA9qQRB2QQJxIgFyayAAIAF0QQ92aiIAQQdqdkEBcSAAQQF0cgsFQQALIgFBAnRBgCRqIQAgCCABNgIcIAhBEGoiBEEANgIEIARBADYCACADQQEgAXQiBHFFBEBB1CEgAyAEcjYCACAAIAg2AgAgCCAANgIYIAggCDYCDCAIIAg2AggMAgsCQCAAKAIAIgAoAgRBeHEgAkYEQCAAIQoFIAJBAEEZIAFBAXZrIAFBH0YbdCEBA0AgAEEQaiABQR92QQJ0aiIEKAIAIgMEQCABQQF0IQEgAygCBEF4cSACRgRAIAMhCgwEBSADIQAMAgsACwtB4CEoAgAgBEsEQBAGBSAEIAg2AgAgCCAANgIYIAggCDYCDCAIIAg2AggMBAsLC0HgISgCACIDIApBCGoiASgCACIATSADIApNcQRAIAAgCDYCDCABIAg2AgAgCCAANgIIIAggCjYCDCAIQQA2AhgFEAYLCwsgDiQGIAVBCGoPBSAECwUgBAsFIAQLCwsLIQNB2CEoAgAiASADTwRAQeQhKAIAIQAgASADayICQQ9LBEBB5CEgACADaiIENgIAQdghIAI2AgAgBCACQQFyNgIEIAAgAWogAjYCACAAIANBA3I2AgQFQdghQQA2AgBB5CFBADYCACAAIAFBA3I2AgQgACABakEEaiIDIAMoAgBBAXI2AgALDAILQdwhKAIAIgEgA0sEQEHcISABIANrIgE2AgAMAQtBqCUoAgAEf0GwJSgCAAVBsCVBgCA2AgBBrCVBgCA2AgBBtCVBfzYCAEG4JUF/NgIAQbwlQQA2AgBBjCVBADYCAEGoJSAXQXBxQdiq1aoFczYCAEGAIAsiACADQS9qIgZqIgVBACAAayIHcSIEIANNBEAgDiQGQQAPC0GIJSgCACIABEBBgCUoAgAiAiAEaiIKIAJNIAogAEtyBEAgDiQGQQAPCwsgA0EwaiEKAkACQEGMJSgCAEEEcQRAQQAhAQUCQAJAAkBB6CEoAgAiAEUNAEGQJSECA0ACQCACKAIAIg0gAE0EQCANIAIoAgRqIABLDQELIAIoAggiAg0BDAILCyAFIAFrIAdxIgFB/////wdJBEAgARB7IgAgAigCACACKAIEakYEQCAAQX9HDQYFDAMLBUEAIQELDAILQQAQeyIAQX9GBH9BAAVBrCUoAgAiAUF/aiICIABqQQAgAWtxIABrQQAgAiAAcRsgBGoiAUGAJSgCACIFaiECIAEgA0sgAUH/////B0lxBH9BiCUoAgAiBwRAIAIgBU0gAiAHS3IEQEEAIQEMBQsLIAEQeyICIABGDQUgAiEADAIFQQALCyEBDAELIAogAUsgAUH/////B0kgAEF/R3FxRQRAIABBf0YEQEEAIQEMAgUMBAsACyAGIAFrQbAlKAIAIgJqQQAgAmtxIgJB/////wdPDQJBACABayEGIAIQe0F/RgR/IAYQexpBAAUgAiABaiEBDAMLIQELQYwlQYwlKAIAQQRyNgIACyAEQf////8HSQRAIAQQeyEAQQAQeyICIABrIgYgA0EoakshBCAGIAEgBBshASAAQX9GIARBAXNyIAAgAkkgAEF/RyACQX9HcXFBAXNyRQ0BCwwBC0GAJUGAJSgCACABaiICNgIAIAJBhCUoAgBLBEBBhCUgAjYCAAsCQEHoISgCACIGBEBBkCUhAgJAAkADQCAAIAIoAgAiBCACKAIEIgVqRg0BIAIoAggiAg0ACwwBCyACQQRqIQcgAigCDEEIcUUEQCAAIAZLIAQgBk1xBEAgByAFIAFqNgIAIAZBACAGQQhqIgBrQQdxQQAgAEEHcRsiAmohAEHcISgCACABaiIEIAJrIQFB6CEgADYCAEHcISABNgIAIAAgAUEBcjYCBCAGIARqQSg2AgRB7CFBuCUoAgA2AgAMBAsLCyAAQeAhKAIAIgJJBEBB4CEgADYCACAAIQILIAAgAWohBUGQJSEEAkACQANAIAQoAgAgBUYNASAEKAIIIgQNAAsMAQsgBCgCDEEIcUUEQCAEIAA2AgAgBEEEaiIEIAQoAgAgAWo2AgAgAEEAIABBCGoiAGtBB3FBACAAQQdxG2oiCCADaiEHIAVBACAFQQhqIgBrQQdxQQAgAEEHcRtqIgEgCGsgA2shBCAIIANBA3I2AgQCQCAGIAFGBEBB3CFB3CEoAgAgBGoiADYCAEHoISAHNgIAIAcgAEEBcjYCBAVB5CEoAgAgAUYEQEHYIUHYISgCACAEaiIANgIAQeQhIAc2AgAgByAAQQFyNgIEIAcgAGogADYCAAwCCyABKAIEIgBBA3FBAUYEfyAAQXhxIQ0gAEEDdiEFAkAgAEGAAkkEQCABKAIMIQMCQCABKAIIIgYgBUEDdEH4IWoiAEcEQCACIAZLBEAQBgsgBigCDCABRg0BEAYLCyADIAZGBEBB0CFB0CEoAgBBASAFdEF/c3E2AgAMAgsCQCADIABGBEAgA0EIaiEUBSACIANLBEAQBgsgA0EIaiIAKAIAIAFGBEAgACEUDAILEAYLCyAGIAM2AgwgFCAGNgIABSABKAIYIQoCQCABKAIMIgAgAUYEQCABQRBqIgNBBGoiBigCACIABEAgBiEDBSADKAIAIgBFDQILA0ACQCAAQRRqIgYoAgAiBUUEQCAAQRBqIgYoAgAiBUUNAQsgBiEDIAUhAAwBCwsgAiADSwRAEAYFIANBADYCACAAIQkLBSACIAEoAggiA0sEQBAGCyADQQxqIgIoAgAgAUcEQBAGCyAAQQhqIgYoAgAgAUYEQCACIAA2AgAgBiADNgIAIAAhCQUQBgsLCyAKRQ0BAkAgASgCHCIAQQJ0QYAkaiIDKAIAIAFGBEAgAyAJNgIAIAkNAUHUIUHUISgCAEEBIAB0QX9zcTYCAAwDBUHgISgCACAKSwRAEAYFIApBEGoiACAKQRRqIAAoAgAgAUYbIAk2AgAgCUUNBAsLC0HgISgCACIDIAlLBEAQBgsgCSAKNgIYIAFBEGoiAigCACIABEAgAyAASwRAEAYFIAkgADYCECAAIAk2AhgLCyACKAIEIgBFDQFB4CEoAgAgAEsEQBAGBSAJIAA2AhQgACAJNgIYCwsLIAEgDWohASANIARqBSAECyECIAFBBGoiACAAKAIAQX5xNgIAIAcgAkEBcjYCBCAHIAJqIAI2AgAgAkEDdiEDIAJBgAJJBEAgA0EDdEH4IWohAAJAQdAhKAIAIgFBASADdCIDcQRAQeAhKAIAIABBCGoiAygCACIBTQRAIAEhDyADIRUMAgsQBgVB0CEgASADcjYCACAAIQ8gAEEIaiEVCwsgFSAHNgIAIA8gBzYCDCAHIA82AgggByAANgIMDAILAn8gAkEIdiIABH9BHyACQf///wdLDQEaIAJBDiAAIABBgP4/akEQdkEIcSIAdCIDQYDgH2pBEHZBBHEiASAAciADIAF0IgBBgIAPakEQdkECcSIDcmsgACADdEEPdmoiAEEHanZBAXEgAEEBdHIFQQALCyIDQQJ0QYAkaiEAIAcgAzYCHCAHQRBqIgFBADYCBCABQQA2AgBB1CEoAgAiAUEBIAN0IgRxRQRAQdQhIAEgBHI2AgAgACAHNgIAIAcgADYCGCAHIAc2AgwgByAHNgIIDAILAkAgACgCACIAKAIEQXhxIAJGBEAgACELBSACQQBBGSADQQF2ayADQR9GG3QhAQNAIABBEGogAUEfdkECdGoiBCgCACIDBEAgAUEBdCEBIAMoAgRBeHEgAkYEQCADIQsMBAUgAyEADAILAAsLQeAhKAIAIARLBEAQBgUgBCAHNgIAIAcgADYCGCAHIAc2AgwgByAHNgIIDAQLCwtB4CEoAgAiAyALQQhqIgEoAgAiAE0gAyALTXEEQCAAIAc2AgwgASAHNgIAIAcgADYCCCAHIAs2AgwgB0EANgIYBRAGCwsLIA4kBiAIQQhqDwsLQZAlIQIDQAJAIAIoAgAiBCAGTQRAIAQgAigCBGoiBSAGSw0BCyACKAIIIQIMAQsLIAVBUWoiBEEIaiECIAYgBEEAIAJrQQdxQQAgAkEHcRtqIgIgAiAGQRBqIglJGyICQQhqIQRB6CEgAEEAIABBCGoiB2tBB3FBACAHQQdxGyIHaiIKNgIAQdwhIAFBWGoiCyAHayIHNgIAIAogB0EBcjYCBCAAIAtqQSg2AgRB7CFBuCUoAgA2AgAgAkEEaiIHQRs2AgAgBEGQJSkCADcCACAEQZglKQIANwIIQZAlIAA2AgBBlCUgATYCAEGcJUEANgIAQZglIAQ2AgAgAkEYaiEAA0AgAEEEaiIBQQc2AgAgAEEIaiAFSQRAIAEhAAwBCwsgAiAGRwRAIAcgBygCAEF+cTYCACAGIAIgBmsiBEEBcjYCBCACIAQ2AgAgBEEDdiEBIARBgAJJBEAgAUEDdEH4IWohAEHQISgCACICQQEgAXQiAXEEQEHgISgCACAAQQhqIgEoAgAiAksEQBAGBSACIREgASEWCwVB0CEgAiABcjYCACAAIREgAEEIaiEWCyAWIAY2AgAgESAGNgIMIAYgETYCCCAGIAA2AgwMAwsgBEEIdiIABH8gBEH///8HSwR/QR8FIARBDiAAIABBgP4/akEQdkEIcSIAdCIBQYDgH2pBEHZBBHEiAiAAciABIAJ0IgBBgIAPakEQdkECcSIBcmsgACABdEEPdmoiAEEHanZBAXEgAEEBdHILBUEACyIBQQJ0QYAkaiEAIAYgATYCHCAGQQA2AhQgCUEANgIAQdQhKAIAIgJBASABdCIFcUUEQEHUISACIAVyNgIAIAAgBjYCACAGIAA2AhggBiAGNgIMIAYgBjYCCAwDCwJAIAAoAgAiACgCBEF4cSAERgRAIAAhCAUgBEEAQRkgAUEBdmsgAUEfRht0IQIDQCAAQRBqIAJBH3ZBAnRqIgUoAgAiAQRAIAJBAXQhAiABKAIEQXhxIARGBEAgASEIDAQFIAEhAAwCCwALC0HgISgCACAFSwRAEAYFIAUgBjYCACAGIAA2AhggBiAGNgIMIAYgBjYCCAwFCwsLQeAhKAIAIgEgCEEIaiICKAIAIgBNIAEgCE1xBEAgACAGNgIMIAIgBjYCACAGIAA2AgggBiAINgIMIAZBADYCGAUQBgsLBUHgISgCACICRSAAIAJJcgRAQeAhIAA2AgALQZAlIAA2AgBBlCUgATYCAEGcJUEANgIAQfQhQaglKAIANgIAQfAhQX82AgBBhCJB+CE2AgBBgCJB+CE2AgBBjCJBgCI2AgBBiCJBgCI2AgBBlCJBiCI2AgBBkCJBiCI2AgBBnCJBkCI2AgBBmCJBkCI2AgBBpCJBmCI2AgBBoCJBmCI2AgBBrCJBoCI2AgBBqCJBoCI2AgBBtCJBqCI2AgBBsCJBqCI2AgBBvCJBsCI2AgBBuCJBsCI2AgBBxCJBuCI2AgBBwCJBuCI2AgBBzCJBwCI2AgBByCJBwCI2AgBB1CJByCI2AgBB0CJByCI2AgBB3CJB0CI2AgBB2CJB0CI2AgBB5CJB2CI2AgBB4CJB2CI2AgBB7CJB4CI2AgBB6CJB4CI2AgBB9CJB6CI2AgBB8CJB6CI2AgBB/CJB8CI2AgBB+CJB8CI2AgBBhCNB+CI2AgBBgCNB+CI2AgBBjCNBgCM2AgBBiCNBgCM2AgBBlCNBiCM2AgBBkCNBiCM2AgBBnCNBkCM2AgBBmCNBkCM2AgBBpCNBmCM2AgBBoCNBmCM2AgBBrCNBoCM2AgBBqCNBoCM2AgBBtCNBqCM2AgBBsCNBqCM2AgBBvCNBsCM2AgBBuCNBsCM2AgBBxCNBuCM2AgBBwCNBuCM2AgBBzCNBwCM2AgBByCNBwCM2AgBB1CNByCM2AgBB0CNByCM2AgBB3CNB0CM2AgBB2CNB0CM2AgBB5CNB2CM2AgBB4CNB2CM2AgBB7CNB4CM2AgBB6CNB4CM2AgBB9CNB6CM2AgBB8CNB6CM2AgBB/CNB8CM2AgBB+CNB8CM2AgBB6CEgAEEAIABBCGoiAmtBB3FBACACQQdxGyICaiIENgIAQdwhIAFBWGoiASACayICNgIAIAQgAkEBcjYCBCAAIAFqQSg2AgRB7CFBuCUoAgA2AgALC0HcISgCACIAIANLBEBB3CEgACADayIBNgIADAILCxBjQQw2AgAgDiQGQQAPC0HoIUHoISgCACIAIANqIgI2AgAgAiABQQFyNgIEIAAgA0EDcjYCBAsgDiQGIABBCGoLrRIBEX8gAEUEQA8LIABBeGoiBEHgISgCACIMSQRAEAYLIABBfGooAgAiAEEDcSILQQFGBEAQBgsgBCAAQXhxIgJqIQcCQCAAQQFxBEAgAiEBIAQiAyEFBSAEKAIAIQkgC0UEQA8LIAQgCWsiACAMSQRAEAYLIAkgAmohBEHkISgCACAARgRAIAdBBGoiASgCACIDQQNxQQNHBEAgACEDIAQhASAAIQUMAwtB2CEgBDYCACABIANBfnE2AgAgACAEQQFyNgIEIAAgBGogBDYCAA8LIAlBA3YhAiAJQYACSQRAIAAoAgwhAyAAKAIIIgUgAkEDdEH4IWoiAUcEQCAMIAVLBEAQBgsgBSgCDCAARwRAEAYLCyADIAVGBEBB0CFB0CEoAgBBASACdEF/c3E2AgAgACEDIAQhASAAIQUMAwsgAyABRgRAIANBCGohBgUgDCADSwRAEAYLIANBCGoiASgCACAARgRAIAEhBgUQBgsLIAUgAzYCDCAGIAU2AgAgACEDIAQhASAAIQUMAgsgACgCGCENAkAgACgCDCICIABGBEAgAEEQaiIGQQRqIgkoAgAiAgRAIAkhBgUgBigCACICRQ0CCwNAAkAgAkEUaiIJKAIAIgtFBEAgAkEQaiIJKAIAIgtFDQELIAkhBiALIQIMAQsLIAwgBksEQBAGBSAGQQA2AgAgAiEICwUgDCAAKAIIIgZLBEAQBgsgBkEMaiIJKAIAIABHBEAQBgsgAkEIaiILKAIAIABGBEAgCSACNgIAIAsgBjYCACACIQgFEAYLCwsgDQRAIAAoAhwiAkECdEGAJGoiBigCACAARgRAIAYgCDYCACAIRQRAQdQhQdQhKAIAQQEgAnRBf3NxNgIAIAAhAyAEIQEgACEFDAQLBUHgISgCACANSwRAEAYFIA1BEGoiAiANQRRqIAIoAgAgAEYbIAg2AgAgCEUEQCAAIQMgBCEBIAAhBQwFCwsLQeAhKAIAIgYgCEsEQBAGCyAIIA02AhggAEEQaiIJKAIAIgIEQCAGIAJLBEAQBgUgCCACNgIQIAIgCDYCGAsLIAkoAgQiAgRAQeAhKAIAIAJLBEAQBgUgCCACNgIUIAIgCDYCGCAAIQMgBCEBIAAhBQsFIAAhAyAEIQEgACEFCwUgACEDIAQhASAAIQULCwsgBSAHTwRAEAYLIAdBBGoiBCgCACIAQQFxRQRAEAYLIABBAnEEfyAEIABBfnE2AgAgAyABQQFyNgIEIAUgAWogATYCACABBUHoISgCACAHRgRAQdwhQdwhKAIAIAFqIgA2AgBB6CEgAzYCACADIABBAXI2AgQgA0HkISgCAEcEQA8LQeQhQQA2AgBB2CFBADYCAA8LQeQhKAIAIAdGBEBB2CFB2CEoAgAgAWoiADYCAEHkISAFNgIAIAMgAEEBcjYCBCAFIABqIAA2AgAPCyAAQXhxIAFqIQQgAEEDdiEGAkAgAEGAAkkEQCAHKAIMIQEgBygCCCICIAZBA3RB+CFqIgBHBEBB4CEoAgAgAksEQBAGCyACKAIMIAdHBEAQBgsLIAEgAkYEQEHQIUHQISgCAEEBIAZ0QX9zcTYCAAwCCyABIABGBEAgAUEIaiEQBUHgISgCACABSwRAEAYLIAFBCGoiACgCACAHRgRAIAAhEAUQBgsLIAIgATYCDCAQIAI2AgAFIAcoAhghCAJAIAcoAgwiACAHRgRAIAdBEGoiAUEEaiICKAIAIgAEQCACIQEFIAEoAgAiAEUNAgsDQAJAIABBFGoiAigCACIGRQRAIABBEGoiAigCACIGRQ0BCyACIQEgBiEADAELC0HgISgCACABSwRAEAYFIAFBADYCACAAIQoLBUHgISgCACAHKAIIIgFLBEAQBgsgAUEMaiICKAIAIAdHBEAQBgsgAEEIaiIGKAIAIAdGBEAgAiAANgIAIAYgATYCACAAIQoFEAYLCwsgCARAIAcoAhwiAEECdEGAJGoiASgCACAHRgRAIAEgCjYCACAKRQRAQdQhQdQhKAIAQQEgAHRBf3NxNgIADAQLBUHgISgCACAISwRAEAYFIAhBEGoiACAIQRRqIAAoAgAgB0YbIAo2AgAgCkUNBAsLQeAhKAIAIgEgCksEQBAGCyAKIAg2AhggB0EQaiICKAIAIgAEQCABIABLBEAQBgUgCiAANgIQIAAgCjYCGAsLIAIoAgQiAARAQeAhKAIAIABLBEAQBgUgCiAANgIUIAAgCjYCGAsLCwsLIAMgBEEBcjYCBCAFIARqIAQ2AgAgA0HkISgCAEYEf0HYISAENgIADwUgBAsLIgVBA3YhASAFQYACSQRAIAFBA3RB+CFqIQBB0CEoAgAiBUEBIAF0IgFxBEBB4CEoAgAgAEEIaiIBKAIAIgVLBEAQBgUgBSEPIAEhEQsFQdAhIAUgAXI2AgAgACEPIABBCGohEQsgESADNgIAIA8gAzYCDCADIA82AgggAyAANgIMDwsgBUEIdiIABH8gBUH///8HSwR/QR8FIAVBDiAAIABBgP4/akEQdkEIcSIAdCIBQYDgH2pBEHZBBHEiBCAAciABIAR0IgBBgIAPakEQdkECcSIBcmsgACABdEEPdmoiAEEHanZBAXEgAEEBdHILBUEACyIBQQJ0QYAkaiEAIAMgATYCHCADQQA2AhQgA0EANgIQAkBB1CEoAgAiBEEBIAF0IgJxBEACQCAAKAIAIgAoAgRBeHEgBUYEQCAAIQ4FIAVBAEEZIAFBAXZrIAFBH0YbdCEEA0AgAEEQaiAEQR92QQJ0aiICKAIAIgEEQCAEQQF0IQQgASgCBEF4cSAFRgRAIAEhDgwEBSABIQAMAgsACwtB4CEoAgAgAksEQBAGBSACIAM2AgAgAyAANgIYIAMgAzYCDCADIAM2AggMBAsLC0HgISgCACIBIA5BCGoiBSgCACIATSABIA5NcQRAIAAgAzYCDCAFIAM2AgAgAyAANgIIIAMgDjYCDCADQQA2AhgFEAYLBUHUISAEIAJyNgIAIAAgAzYCACADIAA2AhggAyADNgIMIAMgAzYCCAsLQfAhQfAhKAIAQX9qIgA2AgAgAARADwtBmCUhAANAIAAoAgAiAUEIaiEAIAENAAtB8CFBfzYCAAuAAQECfyAARQRAIAEQXg8LIAFBv39LBEAQY0EMNgIAQQAPCyAAQXhqQRAgAUELakF4cSABQQtJGxBhIgIEQCACQQhqDwsgARBeIgJFBEBBAA8LIAIgACAAQXxqKAIAIgNBeHFBBEEIIANBA3EbayIDIAEgAyABSRsQeRogABBfIAILmAkBDH8CQCAAIABBBGoiCigCACIIQXhxIgJqIQUgCEEDcSIJQQFHQeAhKAIAIgsgAE1xIAUgAEtxRQRAEAYLIAVBBGoiBygCACIEQQFxRQRAEAYLIAlFBEAgAUGAAkkNASACIAFBBGpPBEAgAiABa0GwJSgCAEEBdE0EQCAADwsLDAELIAIgAU8EQCACIAFrIgNBD00EQCAADwsgCiAIQQFxIAFyQQJyNgIAIAAgAWoiASADQQNyNgIEIAcgBygCAEEBcjYCACABIAMQYiAADwtB6CEoAgAgBUYEQEHcISgCACACaiIDIAFNDQEgCiAIQQFxIAFyQQJyNgIAIAAgAWoiAiADIAFrIgFBAXI2AgRB6CEgAjYCAEHcISABNgIAIAAPC0HkISgCACAFRgRAQdghKAIAIAJqIgIgAUkNASACIAFrIgNBD0sEQCAKIAhBAXEgAXJBAnI2AgAgACABaiIBIANBAXI2AgQgACACaiICIAM2AgAgAkEEaiICIAIoAgBBfnE2AgAFIAogCEEBcSACckECcjYCACAAIAJqQQRqIgEgASgCAEEBcjYCAEEAIQFBACEDC0HYISADNgIAQeQhIAE2AgAgAA8LIARBAnENACAEQXhxIAJqIgwgAUkNACAMIAFrIQ0gBEEDdiECAkAgBEGAAkkEQCAFKAIMIQYgBSgCCCIEIAJBA3RB+CFqIgdHBEAgCyAESwRAEAYLIAQoAgwgBUcEQBAGCwsgBiAERgRAQdAhQdAhKAIAQQEgAnRBf3NxNgIADAILIAYgB0YEQCAGQQhqIQMFIAsgBksEQBAGCyAGQQhqIgIoAgAgBUYEQCACIQMFEAYLCyAEIAY2AgwgAyAENgIABSAFKAIYIQkCQCAFKAIMIgMgBUYEQCAFQRBqIgJBBGoiBCgCACIDBEAgBCECBSACKAIAIgNFDQILA0ACQCADQRRqIgQoAgAiB0UEQCADQRBqIgQoAgAiB0UNAQsgBCECIAchAwwBCwsgCyACSwRAEAYFIAJBADYCACADIQYLBSALIAUoAggiAksEQBAGCyACQQxqIgQoAgAgBUcEQBAGCyADQQhqIgcoAgAgBUYEQCAEIAM2AgAgByACNgIAIAMhBgUQBgsLCyAJBEAgBSgCHCIDQQJ0QYAkaiICKAIAIAVGBEAgAiAGNgIAIAZFBEBB1CFB1CEoAgBBASADdEF/c3E2AgAMBAsFQeAhKAIAIAlLBEAQBgUgCUEQaiIDIAlBFGogAygCACAFRhsgBjYCACAGRQ0ECwtB4CEoAgAiAiAGSwRAEAYLIAYgCTYCGCAFQRBqIgQoAgAiAwRAIAIgA0sEQBAGBSAGIAM2AhAgAyAGNgIYCwsgBCgCBCIDBEBB4CEoAgAgA0sEQBAGBSAGIAM2AhQgAyAGNgIYCwsLCwsgDUEQSQRAIAogCEEBcSAMckECcjYCACAAIAxqQQRqIgEgASgCAEEBcjYCAAUgCiAIQQFxIAFyQQJyNgIAIAAgAWoiASANQQNyNgIEIAAgDGpBBGoiAyADKAIAQQFyNgIAIAEgDRBiCyAADwtBAAvxEAEOfwJAIAAgAWohBgJAIAAoAgQiB0EBcQRAIAAhAiABIQQFIAAoAgAhBSAHQQNxRQRADwsgACAFayIAQeAhKAIAIgxJBEAQBgsgBSABaiEBQeQhKAIAIABGBEAgBkEEaiIEKAIAIgJBA3FBA0cEQCAAIQIgASEEDAMLQdghIAE2AgAgBCACQX5xNgIAIAAgAUEBcjYCBCAGIAE2AgAPCyAFQQN2IQcgBUGAAkkEQCAAKAIMIQIgACgCCCIFIAdBA3RB+CFqIgRHBEAgDCAFSwRAEAYLIAUoAgwgAEcEQBAGCwsgAiAFRgRAQdAhQdAhKAIAQQEgB3RBf3NxNgIAIAAhAiABIQQMAwsgAiAERgRAIAJBCGohAwUgDCACSwRAEAYLIAJBCGoiBCgCACAARgRAIAQhAwUQBgsLIAUgAjYCDCADIAU2AgAgACECIAEhBAwCCyAAKAIYIQoCQCAAKAIMIgMgAEYEQCAAQRBqIgVBBGoiBygCACIDBEAgByEFBSAFKAIAIgNFDQILA0ACQCADQRRqIgcoAgAiC0UEQCADQRBqIgcoAgAiC0UNAQsgByEFIAshAwwBCwsgDCAFSwRAEAYFIAVBADYCACADIQgLBSAMIAAoAggiBUsEQBAGCyAFQQxqIgcoAgAgAEcEQBAGCyADQQhqIgsoAgAgAEYEQCAHIAM2AgAgCyAFNgIAIAMhCAUQBgsLCyAKBEAgACgCHCIDQQJ0QYAkaiIFKAIAIABGBEAgBSAINgIAIAhFBEBB1CFB1CEoAgBBASADdEF/c3E2AgAgACECIAEhBAwECwVB4CEoAgAgCksEQBAGBSAKQRBqIgMgCkEUaiADKAIAIABGGyAINgIAIAhFBEAgACECIAEhBAwFCwsLQeAhKAIAIgUgCEsEQBAGCyAIIAo2AhggAEEQaiIHKAIAIgMEQCAFIANLBEAQBgUgCCADNgIQIAMgCDYCGAsLIAcoAgQiAwRAQeAhKAIAIANLBEAQBgUgCCADNgIUIAMgCDYCGCAAIQIgASEECwUgACECIAEhBAsFIAAhAiABIQQLCwsgBkHgISgCACIHSQRAEAYLIAZBBGoiASgCACIAQQJxBEAgASAAQX5xNgIAIAIgBEEBcjYCBCACIARqIAQ2AgAFQeghKAIAIAZGBEBB3CFB3CEoAgAgBGoiADYCAEHoISACNgIAIAIgAEEBcjYCBCACQeQhKAIARwRADwtB5CFBADYCAEHYIUEANgIADwtB5CEoAgAgBkYEQEHYIUHYISgCACAEaiIANgIAQeQhIAI2AgAgAiAAQQFyNgIEIAIgAGogADYCAA8LIABBeHEgBGohBCAAQQN2IQUCQCAAQYACSQRAIAYoAgwhASAGKAIIIgMgBUEDdEH4IWoiAEcEQCAHIANLBEAQBgsgAygCDCAGRwRAEAYLCyABIANGBEBB0CFB0CEoAgBBASAFdEF/c3E2AgAMAgsgASAARgRAIAFBCGohDgUgByABSwRAEAYLIAFBCGoiACgCACAGRgRAIAAhDgUQBgsLIAMgATYCDCAOIAM2AgAFIAYoAhghCAJAIAYoAgwiACAGRgRAIAZBEGoiAUEEaiIDKAIAIgAEQCADIQEFIAEoAgAiAEUNAgsDQAJAIABBFGoiAygCACIFRQRAIABBEGoiAygCACIFRQ0BCyADIQEgBSEADAELCyAHIAFLBEAQBgUgAUEANgIAIAAhCQsFIAcgBigCCCIBSwRAEAYLIAFBDGoiAygCACAGRwRAEAYLIABBCGoiBSgCACAGRgRAIAMgADYCACAFIAE2AgAgACEJBRAGCwsLIAgEQCAGKAIcIgBBAnRBgCRqIgEoAgAgBkYEQCABIAk2AgAgCUUEQEHUIUHUISgCAEEBIAB0QX9zcTYCAAwECwVB4CEoAgAgCEsEQBAGBSAIQRBqIgAgCEEUaiAAKAIAIAZGGyAJNgIAIAlFDQQLC0HgISgCACIBIAlLBEAQBgsgCSAINgIYIAZBEGoiAygCACIABEAgASAASwRAEAYFIAkgADYCECAAIAk2AhgLCyADKAIEIgAEQEHgISgCACAASwRAEAYFIAkgADYCFCAAIAk2AhgLCwsLCyACIARBAXI2AgQgAiAEaiAENgIAIAJB5CEoAgBGBEBB2CEgBDYCAA8LCyAEQQN2IQEgBEGAAkkEQCABQQN0QfghaiEAQdAhKAIAIgRBASABdCIBcQRAQeAhKAIAIABBCGoiASgCACIESwRAEAYFIAQhDSABIQ8LBUHQISAEIAFyNgIAIAAhDSAAQQhqIQ8LIA8gAjYCACANIAI2AgwgAiANNgIIIAIgADYCDA8LIARBCHYiAAR/IARB////B0sEf0EfBSAEQQ4gACAAQYD+P2pBEHZBCHEiAHQiAUGA4B9qQRB2QQRxIgMgAHIgASADdCIAQYCAD2pBEHZBAnEiAXJrIAAgAXRBD3ZqIgBBB2p2QQFxIABBAXRyCwVBAAsiAUECdEGAJGohACACIAE2AhwgAkEANgIUIAJBADYCEEHUISgCACIDQQEgAXQiBXFFBEBB1CEgAyAFcjYCACAAIAI2AgAMAQsCQCAAKAIAIgAoAgRBeHEgBEYEfyAABSAEQQBBGSABQQF2ayABQR9GG3QhAwNAIABBEGogA0EfdkECdGoiBSgCACIBBEAgA0EBdCEDIAEoAgRBeHEgBEYNAyABIQAMAQsLQeAhKAIAIAVLBEAQBgsgBSACNgIADAILIQELQeAhKAIAIgQgAUEIaiIDKAIAIgBNIAQgAU1xRQRAEAYLIAAgAjYCDCADIAI2AgAgAiAANgIIIAIgATYCDCACQQA2AhgPCyACIAA2AhggAiACNgIMIAIgAjYCCAsFAEHAJQtQAQJ/An8gAgR/A0AgACwAACIDIAEsAAAiBEYEQCAAQQFqIQAgAUEBaiEBQQAgAkF/aiICRQ0DGgwBCwsgA0H/AXEgBEH/AXFrBUEACwsiAAupAQECfyABQf8HSgRAIABEAAAAAAAA4H+iIgBEAAAAAAAA4H+iIAAgAUH+D0oiAhshACABQYJwaiIDQf8HIANB/wdIGyABQYF4aiACGyEBBSABQYJ4SARAIABEAAAAAAAAEACiIgBEAAAAAAAAEACiIAAgAUGEcEgiAhshACABQfwPaiIDQYJ4IANBgnhKGyABQf4HaiACGyEBCwsgACABQf8Haq1CNIa/oguaBAEIfyMGIQojBkHQAWokBiAKIgdBwAFqIgRCATcDAAJAIAIgAWwiCwRAQQAgAmshCSAHIAI2AgQgByACNgIAQQIhBiACIQUgAiEBA0AgByAGQQJ0aiAFIAJqIAFqIgg2AgAgBkEBaiEGIAggC0kEQCABIQUgCCEBDAELCyAAIAtqIAlqIgYgAEsEQCAGIQhBASEBQQEhBQNAIAVBA3FBA0YEfyAAIAIgAyABIAcQZyAEQQIQaCABQQJqBSAHIAFBf2oiBUECdGooAgAgCCAAa0kEQCAAIAIgAyABIAcQZwUgACACIAMgBCABQQAgBxBpCyABQQFGBH8gBEEBEGpBAAUgBCAFEGpBAQsLIQEgBCAEKAIAQQFyIgU2AgAgACACaiIAIAZJDQALIAEhBgVBASEGQQEhBQsgACACIAMgBCAGQQAgBxBpIARBBGohCCAAIQEgBiEAA0ACfwJAIABBAUYgBUEBRnEEfyAIKAIARQ0FDAEFIABBAkgNASAEQQIQaiAEIAQoAgBBB3M2AgAgBEEBEGggASAHIABBfmoiBUECdGooAgBrIAlqIAIgAyAEIABBf2pBASAHEGkgBEEBEGogBCAEKAIAQQFyIgY2AgAgASAJaiIBIAIgAyAEIAVBASAHEGkgBSEAIAYLDAELIAQgBBBrIgUQaCABIAlqIQEgBSAAaiEAIAQoAgALIQUMAAALAAsLIAokBgvgAQEIfyMGIQojBkHwAWokBiAKIgggADYCAAJAIANBAUoEQEEAIAFrIQwgACEGIAMhCUEBIQMgACEFA0AgBSAGIAxqIgcgBCAJQX5qIgZBAnRqKAIAayIAIAJBA3ERAABBf0oEQCAFIAcgAkEDcREAAEF/Sg0DCyAAIAcgAkEDcREAAEF/SiEFIAggA0ECdGohCyADQQFqIQMgBQR/IAsgADYCACAJQX9qBSALIAc2AgAgByEAIAYLIglBAUoEQCAAIQYgCCgCACEFDAELCwVBASEDCwsgASAIIAMQbSAKJAYLWQEDfyAAQQRqIQIgACABQR9LBH8gACACKAIAIgM2AgAgAkEANgIAIAFBYGohAUEABSAAKAIAIQMgAigCAAsiBEEgIAFrdCADIAF2cjYCACACIAQgAXY2AgALjQMBB38jBiEKIwZB8AFqJAYgCkHoAWoiCSADKAIAIgc2AgAgCUEEaiIMIAMoAgQiAzYCACAKIgsgADYCAAJAAkAgB0EBRyADcgRAQQAgAWshDSAAIAYgBEECdGooAgBrIgggACACQQNxEQAAQQFIBEBBASEDBUEBIQcgBUUhBSAAIQMgCCEAA0AgBSAEQQFKcQRAIAYgBEF+akECdGooAgAhBSADIA1qIgggACACQQNxEQAAQX9KBEAgByEFDAULIAggBWsgACACQQNxEQAAQX9KBEAgByEFDAULCyAHQQFqIQUgCyAHQQJ0aiAANgIAIAkgCRBrIgMQaCADIARqIQQgCSgCAEEBRyAMKAIAQQBHckUEQCAAIQMMBAsgACAGIARBAnRqKAIAayIIIAsoAgAgAkEDcREAAEEBSAR/IAUhA0EABSAAIQMgBSEHQQEhBSAIIQAMAQshBQsLBUEBIQMLIAVFBEAgAyEFIAAhAwwBCwwBCyABIAsgBRBtIAMgASACIAQgBhBnCyAKJAYLVwEDfyAAQQRqIgIgAUEfSwR/IAIgACgCACIDNgIAIABBADYCACABQWBqIQFBAAUgAigCACEDIAAoAgALIgRBICABa3YgAyABdHI2AgAgACAEIAF0NgIACycBAX8gACgCAEF/ahBsIgEEfyABBSAAKAIEEGwiAEEgakEAIAAbCws5AQJ/IAAEQCAAQQFxRQRAA0AgAUEBaiEBIABBAXYhAiAAQQJxRQRAIAIhAAwBCwsLBUEgIQELIAELpAEBBX8jBiEFIwZBgAJqJAYgBSEDAkAgAkECTgRAIAEgAkECdGoiByADNgIAIAAEQANAIAMgASgCACAAQYACIABBgAJJGyIEEHkaQQAhAwNAIAEgA0ECdGoiBigCACABIANBAWoiA0ECdGooAgAgBBB5GiAGIAYoAgAgBGo2AgAgAyACRw0ACyAAIARrIgBFDQMgBygCACEDDAAACwALCwsgBSQGC/4IAwd/AX4EfCMGIQcjBkEwaiQGIAdBEGohBCAHIQUgAL0iCUI/iKchBgJ/AkAgCUIgiKciAkH/////B3EiA0H71L2ABEkEfyACQf//P3FB+8MkRg0BIAZBAEchAiADQf2yi4AESQR/IAIEfyABIABEAABAVPsh+T+gIgBEMWNiGmG00D2gIgo5AwAgASAAIAqhRDFjYhphtNA9oDkDCEF/BSABIABEAABAVPsh+b+gIgBEMWNiGmG00L2gIgo5AwAgASAAIAqhRDFjYhphtNC9oDkDCEEBCwUgAgR/IAEgAEQAAEBU+yEJQKAiAEQxY2IaYbTgPaAiCjkDACABIAAgCqFEMWNiGmG04D2gOQMIQX4FIAEgAEQAAEBU+yEJwKAiAEQxY2IaYbTgvaAiCjkDACABIAAgCqFEMWNiGmG04L2gOQMIQQILCwUgA0G8jPGABEkEQCADQb3714AESQRAIANB/LLLgARGDQMgBgRAIAEgAEQAADB/fNkSQKAiAETKlJOnkQ7pPaAiCjkDACABIAAgCqFEypSTp5EO6T2gOQMIQX0MBQUgASAARAAAMH982RLAoCIARMqUk6eRDum9oCIKOQMAIAEgACAKoUTKlJOnkQ7pvaA5AwhBAwwFCwAFIANB+8PkgARGDQMgBgRAIAEgAEQAAEBU+yEZQKAiAEQxY2IaYbTwPaAiCjkDACABIAAgCqFEMWNiGmG08D2gOQMIQXwMBQUgASAARAAAQFT7IRnAoCIARDFjYhphtPC9oCIKOQMAIAEgACAKoUQxY2IaYbTwvaA5AwhBBAwFCwALAAsgA0H7w+SJBEkNASADQf//v/8HSwRAIAEgACAAoSIAOQMIIAEgADkDAEEADAMLIAlC/////////weDQoCAgICAgICwwQCEvyEAQQAhAgNAIAQgAkEDdGogAKq3Igo5AwAgACAKoUQAAAAAAABwQaIhACACQQFqIgJBAkcNAAsgBCAAOQMQIABEAAAAAAAAAABhBEBBASECA0AgAkF/aiEIIAQgAkEDdGorAwBEAAAAAAAAAABhBEAgCCECDAELCwVBAiECCyAEIAUgA0EUdkHqd2ogAkEBakEBEG8hAiAFKwMAIQAgBgR/IAEgAJo5AwAgASAFKwMImjkDCEEAIAJrBSABIAA5AwAgASAFKwMIOQMIIAILCwwBCyAARIPIyW0wX+Q/okQAAAAAAAA4Q6BEAAAAAAAAOMOgIguqIQIgASAAIAtEAABAVPsh+T+ioSIKIAtEMWNiGmG00D2iIgChIgw5AwAgA0EUdiIIIAy9QjSIp0H/D3FrQRBKBEAgC0RzcAMuihmjO6IgCiAKIAtEAABgGmG00D2iIgChIgqhIAChoSEAIAEgCiAAoSIMOQMAIAtEwUkgJZqDezmiIAogCiALRAAAAC6KGaM7oiINoSILoSANoaEhDSAIIAy9QjSIp0H/D3FrQTFKBEAgASALIA2hIgw5AwAgDSEAIAshCgsLIAEgCiAMoSAAoTkDCCACCyEBIAckBiABC/8QAhZ/A3wjBiEPIwZBsARqJAYgD0HAAmohECACQX1qQRhtIgVBACAFQQBKGyESIARBAnRBoBBqKAIAIg0gA0F/aiIHakEATgRAIA0gA2ohCSASIAdrIQUDQCAQIAZBA3RqIAVBAEgEfEQAAAAAAAAAAAUgBUECdEGwEGooAgC3CyIbOQMAIAVBAWohBSAGQQFqIgYgCUcNAAsLIA9B4ANqIQwgD0GgAWohCiAPIQ4gAkFoaiASQWhsIhZqIQkgA0EASiEIQQAhBQNAIAgEQCAFIAdqIQtEAAAAAAAAAAAhG0EAIQYDQCAbIAAgBkEDdGorAwAgECALIAZrQQN0aisDAKKgIRsgBkEBaiIGIANHDQALBUQAAAAAAAAAACEbCyAOIAVBA3RqIBs5AwAgBUEBaiEGIAUgDUgEQCAGIQUMAQsLIAlBAEohE0EYIAlrIRRBFyAJayEXIAlFIRggA0EASiEZIA0hBQJAAkACQANAIA4gBUEDdGorAwAhGyAFQQBKIgsEQCAFIQZBACEHA0AgDCAHQQJ0aiAbIBtEAAAAAAAAcD6iqrciG0QAAAAAAABwQaKhqjYCACAOIAZBf2oiCEEDdGorAwAgG6AhGyAHQQFqIQcgBkEBSgRAIAghBgwBCwsLIBsgCRBlIhsgG0QAAAAAAADAP6KcRAAAAAAAACBAoqEiG6ohBiAbIAa3oSEbAkACQAJAIBMEfyAMIAVBf2pBAnRqIggoAgAiESAUdSEHIAggESAHIBR0ayIINgIAIAggF3UhCCAHIAZqIQYMAQUgGAR/IAwgBUF/akECdGooAgBBF3UhCAwCBSAbRAAAAAAAAOA/ZgR/QQIhCAwEBUEACwsLIQgMAgsgCEEASg0ADAELIAYhByALBEBBACEGQQAhCwNAIAwgC0ECdGoiGigCACERAkACQCAGBH9B////ByEVDAEFIBEEf0EBIQZBgICACCEVDAIFQQALCyEGDAELIBogFSARazYCAAsgC0EBaiILIAVHDQALIAYhCwVBACELCyAHQQFqIQYCQCATBEACQAJAAkAgCUEBaw4CAAECCyAMIAVBf2pBAnRqIgcgBygCAEH///8DcTYCAAwDCyAMIAVBf2pBAnRqIgcgBygCAEH///8BcTYCAAsLCyAIQQJGBEBEAAAAAAAA8D8gG6EhGyALBEAgG0QAAAAAAADwPyAJEGWhIRsLQQIhCAsLIBtEAAAAAAAAAABiDQIgBSANSgRAQQAhCyAFIQcDQCAMIAdBf2oiB0ECdGooAgAgC3IhCyAHIA1KDQALIAsNAgtBASEGA0AgBkEBaiEHIAwgDSAGa0ECdGooAgBFBEAgByEGDAELCyAGIAVqIQcDQCAQIAUgA2oiCEEDdGogBUEBaiIGIBJqQQJ0QbAQaigCALc5AwAgGQRARAAAAAAAAAAAIRtBACEFA0AgGyAAIAVBA3RqKwMAIBAgCCAFa0EDdGorAwCioCEbIAVBAWoiBSADRw0ACwVEAAAAAAAAAAAhGwsgDiAGQQN0aiAbOQMAIAYgB0gEQCAGIQUMAQsLIAchBQwAAAsACyAJIQADQCAAQWhqIQAgDCAFQX9qIgVBAnRqKAIARQ0ACyAAIQIgBSEADAELIAwgG0EAIAlrEGUiG0QAAAAAAABwQWYEfyAMIAVBAnRqIBsgG0QAAAAAAABwPqKqIgO3RAAAAAAAAHBBoqGqNgIAIBYgAmohAiAFQQFqBSAJIQIgG6ohAyAFCyIAQQJ0aiADNgIAC0QAAAAAAADwPyACEGUhGyAAQX9KIgcEQCAAIQIDQCAOIAJBA3RqIBsgDCACQQJ0aigCALeiOQMAIBtEAAAAAAAAcD6iIRsgAkF/aiEDIAJBAEoEQCADIQIMAQsLIAcEQCAAIQIDQCAAIAJrIQlBACEDRAAAAAAAAAAAIRsDQCAbIANBA3RBwBJqKwMAIA4gAyACakEDdGorAwCioCEbIANBAWohBSADIA1OIAMgCU9yRQRAIAUhAwwBCwsgCiAJQQN0aiAbOQMAIAJBf2ohAyACQQBKBEAgAyECDAELCwsLAkACQAJAAkAgBA4EAAEBAgMLIAcEQEQAAAAAAAAAACEbA0AgGyAKIABBA3RqKwMAoCEbIABBf2ohAiAAQQBKBEAgAiEADAELCwVEAAAAAAAAAAAhGwsgASAbmiAbIAgbOQMADAILIAcEQEQAAAAAAAAAACEbIAAhAgNAIBsgCiACQQN0aisDAKAhGyACQX9qIQMgAkEASgRAIAMhAgwBCwsFRAAAAAAAAAAAIRsLIAEgGyAbmiAIRSIEGzkDACAKKwMAIBuhIRsgAEEBTgRAQQEhAgNAIBsgCiACQQN0aisDAKAhGyACQQFqIQMgAiAARwRAIAMhAgwBCwsLIAEgGyAbmiAEGzkDCAwBCyAAQQBKBEAgCiAAIgJBA3RqKwMAIRsDQCAKIAJBf2oiA0EDdGoiBCsDACIdIBugIRwgCiACQQN0aiAbIB0gHKGgOQMAIAQgHDkDACACQQFKBEAgAyECIBwhGwwBCwsgAEEBSiIEBEAgCiAAIgJBA3RqKwMAIRsDQCAKIAJBf2oiA0EDdGoiBSsDACIdIBugIRwgCiACQQN0aiAbIB0gHKGgOQMAIAUgHDkDACACQQJKBEAgAyECIBwhGwwBCwsgBARARAAAAAAAAAAAIRsDQCAbIAogAEEDdGorAwCgIRsgAEF/aiECIABBAkoEQCACIQAMAQsLBUQAAAAAAAAAACEbCwVEAAAAAAAAAAAhGwsFRAAAAAAAAAAAIRsLIAorAwAhHCAIBEAgASAcmjkDACABIAorAwiaOQMIIAEgG5o5AxAFIAEgHDkDACABIAorAwg5AwggASAbOQMQCwsgDyQGIAZBB3ELlwEBA3wgACAAoiIDIAMgA6KiIANEfNXPWjrZ5T2iROucK4rm5Vq+oKIgAyADRH3+sVfjHcc+okTVYcEZoAEqv6CiRKb4EBEREYE/oKAhBSADIACiIQQgACAERElVVVVVVcU/oiADIAFEAAAAAAAA4D+iIAQgBaKhoiABoaChIAQgAyAFokRJVVVVVVXFv6CiIACgIAIbIgALCAAgACABEGULlAEBBHwgACAAoiICIAKiIQNEAAAAAAAA8D8gAkQAAAAAAADgP6IiBKEiBUQAAAAAAADwPyAFoSAEoSACIAIgAiACRJAVyxmgAfo+okR3UcEWbMFWv6CiRExVVVVVVaU/oKIgAyADoiACRMSxtL2e7iE+IAJE1DiIvun6qD2ioaJErVKcgE9+kr6goqCiIAAgAaKhoKALxAEBA38jBiECIwZBEGokBiACIQECfCAAvUIgiKdB/////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=__dirname+\"/\",$.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.js\";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)}}();", "/**\n * unit_converter.js\n * purpose: converts soundfont units into more useable values with the use of lookup tables to improve performance\n */\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{\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 {number} timecents\n * @returns {number} seconds\n */\nexport function timecentsToSeconds(timecents)\n{\n if (timecents <= -32767)\n {\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(MAX_ABS_CENT - MIN_ABS_CENT + 1);\nfor (let i = 0; i < absoluteCentLookupTable.length; i++)\n{\n const absoluteCents = MIN_ABS_CENT + i;\n absoluteCentLookupTable[i] = 440 * Math.pow(2, (absoluteCents - 6900) / 1200);\n}\n\n/**\n * Converts absolute cents to hertz\n * @param cents {number} absolute cents\n * @returns {number} hertz\n */\nexport function absCentsToHz(cents)\n{\n if (cents < MIN_ABS_CENT || cents > MAX_ABS_CENT)\n {\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((MAX_DECIBELS - MIN_DECIBELS) * 100 + 1);\nfor (let i = 0; i < decibelLookUpTable.length; i++)\n{\n const decibels = (MIN_DECIBELS * 100 + i) / 100;\n decibelLookUpTable[i] = Math.pow(10, -decibels / 20);\n}\n\n/**\n * convers decibel attenuation to gain\n * @param decibels {number} the decibel attenuation\n * @returns {number} gain\n */\nexport function decibelAttenuationToGain(decibels)\n{\n return decibelLookUpTable[Math.floor((decibels - MIN_DECIBELS) * 100)];\n}", "/**\n * @enum {number}\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 = reserved, 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/**\n * @type {{min: number, max: number, def: number}[]}\n */\nexport const generatorLimits = [];\n// offsets\ngeneratorLimits[generatorTypes.startAddrsOffset] = { min: 0, max: 32768, def: 0 };\ngeneratorLimits[generatorTypes.endAddrOffset] = { min: -32768, max: 32768, def: 0 };\ngeneratorLimits[generatorTypes.startloopAddrsOffset] = { min: -32768, max: 32768, def: 0 };\ngeneratorLimits[generatorTypes.endloopAddrsOffset] = { min: -32768, max: 32768, def: 0 };\ngeneratorLimits[generatorTypes.startAddrsCoarseOffset] = { min: 0, max: 32768, def: 0 };\n\n// pitch influence\ngeneratorLimits[generatorTypes.modLfoToPitch] = { min: -12000, max: 12000, def: 0 };\ngeneratorLimits[generatorTypes.vibLfoToPitch] = { min: -12000, max: 12000, def: 0 };\ngeneratorLimits[generatorTypes.modEnvToPitch] = { min: -12000, max: 12000, def: 0 };\n\n// lowpass\ngeneratorLimits[generatorTypes.initialFilterFc] = { min: 1500, max: 13500, def: 13500 };\ngeneratorLimits[generatorTypes.initialFilterQ] = { min: 0, max: 960, def: 0 };\ngeneratorLimits[generatorTypes.modLfoToFilterFc] = { min: -12000, max: 12000, def: 0 };\ngeneratorLimits[generatorTypes.modEnvToFilterFc] = { min: -12000, max: 12000, def: 0 };\n\ngeneratorLimits[generatorTypes.endAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0 };\n\ngeneratorLimits[generatorTypes.modLfoToVolume] = { min: -960, max: 960, def: 0 };\n\n// effects, pan\ngeneratorLimits[generatorTypes.chorusEffectsSend] = { min: 0, max: 1000, def: 0 };\ngeneratorLimits[generatorTypes.reverbEffectsSend] = { min: 0, max: 1000, def: 0 };\ngeneratorLimits[generatorTypes.pan] = { min: -500, max: 500, def: 0 };\n\n// lfo\ngeneratorLimits[generatorTypes.delayModLFO] = { min: -12000, max: 5000, def: -12000 };\ngeneratorLimits[generatorTypes.freqModLFO] = { min: -16000, max: 4500, def: 0 };\ngeneratorLimits[generatorTypes.delayVibLFO] = { min: -12000, max: 5000, def: -12000 };\ngeneratorLimits[generatorTypes.freqVibLFO] = { min: -16000, max: 4500, def: 0 };\n\n// mod env\ngeneratorLimits[generatorTypes.delayModEnv] = { min: -32768, max: 5000, def: -32768 }; // -32,768 indicates instant phase,\n// this is done to prevent click at the start of filter modenv\ngeneratorLimits[generatorTypes.attackModEnv] = { min: -32768, max: 8000, def: -32768 };\ngeneratorLimits[generatorTypes.holdModEnv] = { min: -12000, max: 5000, def: -12000 };\ngeneratorLimits[generatorTypes.decayModEnv] = { min: -12000, max: 8000, def: -12000 };\ngeneratorLimits[generatorTypes.sustainModEnv] = { min: 0, max: 1000, def: 0 };\ngeneratorLimits[generatorTypes.releaseModEnv] = { min: -7200, max: 8000, def: -12000 }; // min is set to -7200 to prevent lowpass clicks\n// key num to mod env\ngeneratorLimits[generatorTypes.keyNumToModEnvHold] = { min: -1200, max: 1200, def: 0 };\ngeneratorLimits[generatorTypes.keyNumToModEnvDecay] = { min: -1200, max: 1200, def: 0 };\n\n// vol env\ngeneratorLimits[generatorTypes.delayVolEnv] = { min: -12000, max: 5000, def: -12000 };\ngeneratorLimits[generatorTypes.attackVolEnv] = { min: -12000, max: 8000, def: -12000 };\ngeneratorLimits[generatorTypes.holdVolEnv] = { min: -12000, max: 5000, def: -12000 };\ngeneratorLimits[generatorTypes.decayVolEnv] = { min: -12000, max: 8000, def: -12000 };\ngeneratorLimits[generatorTypes.sustainVolEnv] = { min: 0, max: 1440, def: 0 };\ngeneratorLimits[generatorTypes.releaseVolEnv] = { min: -7200, max: 8000, def: -12000 }; // min is set to -7200 prevent clicks\n// key num to vol env\ngeneratorLimits[generatorTypes.keyNumToVolEnvHold] = { min: -1200, max: 1200, def: 0 };\ngeneratorLimits[generatorTypes.keyNumToVolEnvDecay] = { min: -1200, max: 1200, def: 0 };\n\ngeneratorLimits[generatorTypes.startloopAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0 };\ngeneratorLimits[generatorTypes.keyNum] = { min: -1, max: 127, def: -1 };\ngeneratorLimits[generatorTypes.velocity] = { min: -1, max: 127, def: -1 };\n\ngeneratorLimits[generatorTypes.initialAttenuation] = { min: 0, max: 1440, def: 0 };\n\ngeneratorLimits[generatorTypes.endloopAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0 };\n\ngeneratorLimits[generatorTypes.coarseTune] = { min: -120, max: 120, def: 0 };\ngeneratorLimits[generatorTypes.fineTune] = { min: -12700, max: 12700, def: 0 }; // this generator is used as initial pitch, hence this range\ngeneratorLimits[generatorTypes.scaleTuning] = { min: 0, max: 1200, def: 100 };\ngeneratorLimits[generatorTypes.exclusiveClass] = { min: 0, max: 99999, def: 0 };\ngeneratorLimits[generatorTypes.overridingRootKey] = { min: 0 - 1, max: 127, def: -1 };\ngeneratorLimits[generatorTypes.sampleModes] = { min: 0, max: 3, def: 0 };\n\nexport class Generator\n{\n /**\n * The generator's enum number\n * @type {generatorTypes|number}\n */\n generatorType = generatorTypes.INVALID;\n /**\n * The generator's 16-bit value\n * @type {number}\n */\n generatorValue = 0;\n \n /**\n * Constructs a new generator\n * @param type {generatorTypes|number}\n * @param value {number}\n * @param validate {boolean}\n */\n constructor(type = generatorTypes.INVALID, value = 0, validate = true)\n {\n this.generatorType = type;\n if (value === undefined)\n {\n throw new Error(\"No value provided.\");\n }\n this.generatorValue = Math.round(value);\n if (validate)\n {\n const lim = generatorLimits[type];\n \n if (lim !== undefined)\n {\n this.generatorValue = Math.max(lim.min, Math.min(lim.max, this.generatorValue));\n }\n }\n }\n}\n\n/**\n * generator.js\n * purpose: contains enums for generators,\n * and their limis parses reads soundfont generators, sums them and applies limits\n */\n/**\n * @param generatorType {number}\n * @param presetGens {Generator[]}\n * @param instrumentGens {Generator[]}\n */\nexport function addAndClampGenerator(generatorType, presetGens, instrumentGens)\n{\n const limits = generatorLimits[generatorType] || { min: 0, max: 32768, def: 0 };\n let presetGen = presetGens.find(g => g.generatorType === generatorType);\n let presetValue = 0;\n if (presetGen)\n {\n presetValue = presetGen.generatorValue;\n }\n \n let instruGen = instrumentGens.find(g => g.generatorType === generatorType);\n let instruValue = limits.def;\n if (instruGen)\n {\n instruValue = instruGen.generatorValue;\n }\n \n let value = instruValue + presetValue;\n \n // Special case, initial attenuation.\n // Shall get clamped in the volume envelope,\n // so the modulators can be affected by negative generators (the \"Brass\" patch was problematic...)\n if (generatorType === generatorTypes.initialAttenuation)\n {\n return value;\n }\n \n return Math.max(limits.min, Math.min(limits.max, value));\n}", "import { decibelAttenuationToGain, timecentsToSeconds } from \"./unit_converter.js\";\n\nimport { generatorTypes } from \"../../../soundfont/basic_soundfont/generator.js\";\n\n/**\n * volume_envelope.js\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 */\n\nexport class VolumeEnvelope\n{\n /**\n * The envelope's current time in samples\n * @type {number}\n */\n currentSampleTime = 0;\n /**\n * The sample rate in Hz\n * @type {number}\n */\n sampleRate;\n /**\n * The current attenuation of the envelope in dB\n * @type {number}\n */\n currentAttenuationDb = DB_SILENCE;\n /**\n * The current stage of the volume envelope\n * @type {0|1|2|3|4}\n */\n state = 0;\n /**\n * The dB attenuation of the envelope when it entered the release stage\n * @type {number}\n */\n releaseStartDb = DB_SILENCE;\n /**\n * The time in samples relative to the start of the envelope\n * @type {number}\n */\n releaseStartTimeSamples = 0;\n /**\n * The current gain applied to the voice in the release stage\n * @type {number}\n */\n currentReleaseGain = 1;\n /**\n * The attack duration in samples\n * @type {number}\n */\n attackDuration = 0;\n /**\n * The decay duration in samples\n * @type {number}\n */\n decayDuration = 0;\n /**\n * The release duration in samples\n * @type {number}\n */\n releaseDuration = 0;\n /**\n * The voice's absolute attenuation as linear gain\n * @type {number}\n */\n attenuation = 0;\n /**\n * The attenuation target, which the \"attenuation\" property is linearly interpolated towards (gain)\n * @type {number}\n */\n attenuationTargetGain = 0;\n /**\n * The attenuation target, which the \"attenuation\" property is linearly interpolated towards (dB)\n * @type {number}\n */\n attenuationTarget = 0;\n /**\n * The voice's sustain amount in dB, relative to attenuation\n * @type {number}\n */\n sustainDbRelative = 0;\n /**\n * The time in samples to the end of delay stage, relative to the start of the envelope\n * @type {number}\n */\n delayEnd = 0;\n /**\n * The time in samples to the end of attack stage, relative to the start of the envelope\n * @type {number}\n */\n attackEnd = 0;\n /**\n * The time in samples to the end of hold stage, relative to the start of the envelope\n * @type {number}\n */\n holdEnd = 0;\n /**\n * The time in samples to the end of decay stage, relative to the start of the envelope\n * @type {number}\n */\n decayEnd = 0;\n \n /**\n * @param sampleRate {number} Hz\n * @param initialDecay {number} cb\n */\n constructor(sampleRate, initialDecay)\n {\n this.sampleRate = sampleRate;\n /**\n * if sustain stge 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 * @type {boolean}\n */\n this.canEndOnSilentSustain = initialDecay / 10 >= PERCEIVED_DB_SILENCE;\n }\n \n /**\n * Starts the release phase in the envelope\n * @param voice {Voice} the voice this envelope belongs to\n */\n static startRelease(voice)\n {\n voice.volumeEnvelope.releaseStartTimeSamples = voice.volumeEnvelope.currentSampleTime;\n voice.volumeEnvelope.currentReleaseGain = decibelAttenuationToGain(voice.volumeEnvelope.currentAttenuationDb);\n VolumeEnvelope.recalculate(voice);\n }\n \n /**\n * Recalculates the envelope\n * @param voice {Voice} the voice this envelope belongs to\n */\n static recalculate(voice)\n {\n const env = voice.volumeEnvelope;\n const timecentsToSamples = tc =>\n {\n return Math.max(0, Math.floor(timecentsToSeconds(tc) * env.sampleRate));\n };\n // calculate absolute times (they can change so we have to recalculate every time\n env.attenuationTarget = Math.max(\n 0,\n Math.min(voice.modulatedGenerators[generatorTypes.initialAttenuation], 1440)\n ) / 10; // divide by ten to get decibels\n env.attenuationTargetGain = decibelAttenuationToGain(env.attenuationTarget);\n env.sustainDbRelative = Math.min(DB_SILENCE, voice.modulatedGenerators[generatorTypes.sustainVolEnv] / 10);\n const sustainDb = Math.min(DB_SILENCE, env.sustainDbRelative);\n \n // calculate durations\n env.attackDuration = timecentsToSamples(voice.modulatedGenerators[generatorTypes.attackVolEnv]);\n \n // decay: sfspec 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 = voice.modulatedGenerators[generatorTypes.decayVolEnv];\n const keyNumAddition = (60 - voice.targetKey) * voice.modulatedGenerators[generatorTypes.keyNumToVolEnvDecay];\n const fraction = sustainDb / DB_SILENCE;\n env.decayDuration = timecentsToSamples(fullChange + keyNumAddition) * fraction;\n \n env.releaseDuration = timecentsToSamples(voice.modulatedGenerators[generatorTypes.releaseVolEnv]);\n \n // calculate absolute end times for the values\n env.delayEnd = timecentsToSamples(voice.modulatedGenerators[generatorTypes.delayVolEnv]);\n env.attackEnd = env.attackDuration + env.delayEnd;\n \n // make sure to take keyNumToVolEnvHold into account!\n const holdExcursion = (60 - voice.targetKey) * voice.modulatedGenerators[generatorTypes.keyNumToVolEnvHold];\n env.holdEnd = timecentsToSamples(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 {\n // env.currentAttenuationDb = env.attenuationTarget;\n env.state = 2;\n }\n \n // check if voice is in release\n if (voice.isInRelease)\n {\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(0, Math.min(DB_SILENCE, env.sustainDbRelative));\n const fraction = sustainDb / DB_SILENCE;\n env.decayDuration = timecentsToSamples(fullChange + keyNumAddition) * fraction;\n \n switch (env.state)\n {\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 let elapsed = 1 - ((env.attackEnd - env.releaseStartTimeSamples) / 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 case 2:\n env.releaseStartDb = 0;\n break;\n \n case 3:\n env.releaseStartDb = (1 - (env.decayEnd - env.releaseStartTimeSamples) / env.decayDuration) * sustainDb;\n break;\n \n case 4:\n env.releaseStartDb = sustainDb;\n break;\n }\n env.releaseStartDb = Math.max(0, Math.min(env.releaseStartDb, DB_SILENCE));\n if (env.releaseStartDb >= PERCEIVED_DB_SILENCE)\n {\n voice.finished = true;\n }\n env.currentReleaseGain = decibelAttenuationToGain(env.releaseStartDb);\n \n // release: sfspec 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 = (DB_SILENCE - env.releaseStartDb) / DB_SILENCE;\n env.releaseDuration *= releaseFraction;\n \n }\n }\n \n /**\n * Applies volume envelope gain to the given output buffer\n * @param voice {Voice} the voice we're working on\n * @param audioBuffer {Float32Array} the audio buffer to modify\n * @param centibelOffset {number} the centibel offset of volume, for modLFOtoVolume\n * @param smoothingFactor {number} the adjusted smoothing factor for the envelope\n * @description essentially we use approach of 100dB is silence, 0dB is peak, and always add attenuation to that (which is interpolated)\n */\n static apply(voice, audioBuffer, centibelOffset, smoothingFactor)\n {\n const env = voice.volumeEnvelope;\n let decibelOffset = centibelOffset / 10;\n \n const attenuationSmoothing = smoothingFactor;\n \n // RELEASE PHASE\n if (voice.isInRelease)\n {\n let elapsedRelease = env.currentSampleTime - env.releaseStartTimeSamples;\n if (elapsedRelease >= env.releaseDuration)\n {\n for (let i = 0; i < audioBuffer.length; i++)\n {\n audioBuffer[i] = 0;\n }\n voice.finished = true;\n return;\n }\n let dbDifference = DB_SILENCE - env.releaseStartDb;\n for (let i = 0; i < audioBuffer.length; i++)\n {\n // attenuation interpolation\n env.attenuation += (env.attenuationTargetGain - env.attenuation) * attenuationSmoothing;\n let db = (elapsedRelease / env.releaseDuration) * dbDifference + env.releaseStartDb;\n env.currentReleaseGain = env.attenuation * decibelAttenuationToGain(db + decibelOffset);\n audioBuffer[i] *= env.currentReleaseGain;\n env.currentSampleTime++;\n elapsedRelease++;\n }\n \n if (env.currentReleaseGain <= PERCEIVED_GAIN_SILENCE)\n {\n voice.finished = true;\n }\n return;\n }\n \n let filledBuffer = 0;\n switch (env.state)\n {\n case 0:\n // delay phase, no sound is produced\n while (env.currentSampleTime < env.delayEnd)\n {\n env.currentAttenuationDb = DB_SILENCE;\n audioBuffer[filledBuffer] = 0;\n \n env.currentSampleTime++;\n if (++filledBuffer >= audioBuffer.length)\n {\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 {\n // attenuation interpolation\n env.attenuation += (env.attenuationTargetGain - env.attenuation) * attenuationSmoothing;\n \n // Special case: linear gain ramp instead of linear db ramp\n let linearAttenuation = 1 - (env.attackEnd - env.currentSampleTime) / env.attackDuration; // 0 to 1\n audioBuffer[filledBuffer] *= linearAttenuation * env.attenuation * decibelAttenuationToGain(\n 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 {\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 {\n // attenuation interpolation\n env.attenuation += (env.attenuationTargetGain - env.attenuation) * attenuationSmoothing;\n \n audioBuffer[filledBuffer] *= env.attenuation * decibelAttenuationToGain(decibelOffset);\n env.currentAttenuationDb = 0;\n \n env.currentSampleTime++;\n if (++filledBuffer >= audioBuffer.length)\n {\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 {\n // attenuation interpolation\n env.attenuation += (env.attenuationTargetGain - env.attenuation) * attenuationSmoothing;\n \n env.currentAttenuationDb = (1 - (env.decayEnd - env.currentSampleTime) / env.decayDuration) * env.sustainDbRelative;\n audioBuffer[filledBuffer] *= env.attenuation * decibelAttenuationToGain(env.currentAttenuationDb + decibelOffset);\n \n env.currentSampleTime++;\n if (++filledBuffer >= audioBuffer.length)\n {\n return;\n }\n }\n env.state++;\n // fallthrough\n \n case 4:\n if (env.canEndOnSilentSustain && env.sustainDbRelative >= PERCEIVED_DB_SILENCE)\n {\n voice.finished = true;\n }\n // sustain phase: stay at sustain\n while (true)\n {\n // attenuation interpolation\n env.attenuation += (env.attenuationTargetGain - env.attenuation) * attenuationSmoothing;\n \n audioBuffer[filledBuffer] *= env.attenuation * decibelAttenuationToGain(env.sustainDbRelative + decibelOffset);\n env.currentAttenuationDb = env.sustainDbRelative;\n env.currentSampleTime++;\n if (++filledBuffer >= audioBuffer.length)\n {\n return;\n }\n }\n }\n }\n}", "/**\n * indexed_array.js\n * purpose: exteds Uint8Array with a currentIndex property\n */\n\nexport class IndexedByteArray extends Uint8Array\n{\n /**\n * The current index of the array\n * @type {number}\n */\n currentIndex = 0;\n \n /**\n * Creates a new instance of an Uint8Array with a currentIndex property\n * @param args {any} same as for Uint8Array\n */\n constructor(args)\n {\n super(args);\n }\n \n /**\n * @param start {number?}\n * @param end {number?}\n * @returns {IndexedByteArray}\n */\n slice(start, end)\n {\n const a = super.slice(start, end);\n a.currentIndex = 0;\n return a;\n }\n}\n\n\n/**\n * @param arrs {(IndexedByteArray|Uint8Array)[]}\n * @returns {IndexedByteArray|Uint8Array}\n */\nexport function combineArrays(arrs)\n{\n const length = arrs.reduce((sum, current) => sum + current.length, 0);\n const newArr = new IndexedByteArray(length);\n let offset = 0;\n for (const arr of arrs)\n {\n newArr.set(arr, offset);\n offset += arr.length;\n }\n return newArr;\n}", "import { IndexedByteArray } from \"../utils/indexed_array.js\";\n\n/**\n * midi_message.js\n * purpose: contains enums for midi events and controllers and functions to parse them\n */\n\nexport class MIDIMessage\n{\n /**\n * Absolute number of MIDI ticks from the start of the track.\n * @type {number}\n */\n ticks;\n \n /**\n * The MIDI message status byte. Note that for meta events, it is the second byte. (not 0xFF)\n * @type {number}\n */\n messageStatusByte;\n \n /**\n * Message's binary data\n * @type {IndexedByteArray}\n */\n messageData;\n \n /**\n * @param ticks {number}\n * @param byte {number} the message status byte\n * @param data {IndexedByteArray}\n */\n constructor(ticks, byte, data)\n {\n this.ticks = ticks;\n this.messageStatusByte = byte;\n this.messageData = data;\n }\n}\n\n/**\n * Gets the status byte's channel\n * @param statusByte\n * @returns {number} channel is -1 for system messages -2 for meta and -3 for sysex\n */\nexport function getChannel(statusByte)\n{\n const eventType = statusByte & 0xF0;\n const channel = statusByte & 0x0F;\n \n let resultChannel = channel;\n \n switch (eventType)\n {\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 {\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// all the midi statuses dictionary\nexport const messageTypes = {\n noteOff: 0x80,\n noteOn: 0x90,\n polyPressure: 0xA0,\n controllerChange: 0xB0,\n programChange: 0xC0,\n channelPressure: 0xD0,\n pitchBend: 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};\n\n\n/**\n * Gets the event's status and channel from the status byte\n * @param statusByte {number} the status byte\n * @returns {{channel: number, status: number}} channel will be -1 for sysex and meta\n */\nexport function getEvent(statusByte)\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 {\n eventChannel = channel;\n eventStatus = status;\n }\n \n return {\n status: eventStatus,\n channel: eventChannel\n };\n}\n\n\n/**\n * @enum {number}\n */\nexport const midiControllers = {\n bankSelect: 0,\n modulationWheel: 1,\n breathController: 2,\n footController: 4,\n portamentoTime: 5,\n dataEntryMsb: 6,\n mainVolume: 7,\n balance: 8,\n pan: 10,\n expressionController: 11,\n effectControl1: 12,\n effectControl2: 13,\n generalPurposeController1: 16,\n generalPurposeController2: 17,\n generalPurposeController3: 18,\n generalPurposeController4: 19,\n lsbForControl0BankSelect: 32,\n lsbForControl1ModulationWheel: 33,\n lsbForControl2BreathController: 34,\n lsbForControl4FootController: 36,\n lsbForControl5PortamentoTime: 37,\n lsbForControl6DataEntry: 38,\n lsbForControl7MainVolume: 39,\n lsbForControl8Balance: 40,\n lsbForControl10Pan: 42,\n lsbForControl11ExpressionController: 43,\n lsbForControl12EffectControl1: 44,\n lsbForControl13EffectControl2: 45,\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 reverbDepth: 91,\n tremoloDepth: 92,\n chorusDepth: 93,\n detuneDepth: 94,\n phaserDepth: 95,\n dataIncrement: 96,\n dataDecrement: 97,\n NRPNLsb: 98,\n NRPNMsb: 99,\n RPNLsb: 100,\n RPNMsb: 101,\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};\n\n\n/**\n * @type {{\"11\": number, \"12\": number, \"13\": number, \"14\": number, \"8\": number, \"9\": number, \"10\": number}}\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};", "import { SpessaSynthInfo } from \"./loggin.js\";\nimport { consoleColors } from \"./other.js\";\nimport { DEFAULT_PERCUSSION } from \"../synthetizer/synth_constants.js\";\n\nexport const XG_SFX_VOICE = 64;\n\nconst GM2_DEFAULT_BANK = 121;\n\n/**\n * @param sys {SynthSystem}\n * @returns {number}\n */\nexport function getDefaultBank(sys)\n{\n return sys === \"gm2\" ? GM2_DEFAULT_BANK : 0;\n}\n\n/**\n * @param bankNr {number}\n * @returns {boolean}\n */\nexport function isXGDrums(bankNr)\n{\n return bankNr === 120 || bankNr === 126 || bankNr === 127;\n}\n\n/**\n * @param bank {number}\n * @returns {boolean}\n */\nexport function isValidXGMSB(bank)\n{\n return isXGDrums(bank) || bank === XG_SFX_VOICE || bank === GM2_DEFAULT_BANK;\n}\n\n/**\n * Bank select hacks abstracted here\n * @param bankBefore {number} the current bank number\n * @param bank {number} the cc change bank number\n * @param system {SynthSystem} MIDI system\n * @param isLSB {boolean} is bank LSB?\n * @param isDrums {boolean} is drum channel?\n * @param channelNumber {number} channel number\n * @returns {{\n * newBank: number,\n * drumsStatus: 0|1|2\n * }} 0 - unchanged, 1 - OFF, 2 - ON\n */\nexport function parseBankSelect(bankBefore, bank, system, isLSB, isDrums, channelNumber)\n{\n // 64 means SFX in MSB, so it is allowed\n let out = bankBefore;\n let drumsStatus = 0;\n if (isLSB)\n {\n if (isSystemXG(system))\n {\n if (!isValidXGMSB(bank))\n {\n out = bank;\n }\n }\n else if (system === \"gm2\")\n {\n out = bank;\n }\n }\n else\n {\n let canSetBankSelect = true;\n switch (system)\n {\n case \"gm\":\n // gm ignores bank select\n SpessaSynthInfo(\n `%cIgnoring the Bank Select (${bank}), as the synth is in GM mode.`,\n consoleColors.info\n );\n canSetBankSelect = false;\n break;\n \n case \"xg\":\n canSetBankSelect = isValidXGMSB(bank);\n // for xg, if msb is 120, 126 or 127, then it's drums\n if (isXGDrums(bank))\n {\n drumsStatus = 2;\n }\n else\n {\n // drums shall not be disabled on channel 9\n if (channelNumber % 16 !== DEFAULT_PERCUSSION)\n {\n drumsStatus = 1;\n }\n }\n break;\n \n case \"gm2\":\n if (bank === 120)\n {\n drumsStatus = 2;\n }\n else\n {\n if (channelNumber % 16 !== DEFAULT_PERCUSSION)\n {\n drumsStatus = 1;\n }\n }\n }\n \n if (isDrums)\n {\n // 128 for percussion channel\n bank = 128;\n }\n if (bank === 128 && !isDrums)\n {\n // if a channel is not for percussion, default to bank current\n bank = bankBefore;\n }\n if (canSetBankSelect)\n {\n out = bank;\n }\n }\n return {\n newBank: out,\n drumsStatus: drumsStatus\n };\n}\n\n\n/**\n * Chooses a bank number according to spessasynth logic\n * That is:\n * for GS, bank MSB if not drum, otherwise 128\n * for XG: bank MSB if drum and MSB is valid, 128 othewise, bank MSB if it is SFX voice, LSB otherwise\n * @param msb {number}\n * @param lsb {number}\n * @param isDrums {boolean}\n * @param isXG {boolean}\n * @returns {number}\n */\nexport function chooseBank(msb, lsb, isDrums, isXG)\n{\n if (isXG)\n {\n if (isDrums)\n {\n if (isXGDrums(msb))\n {\n return msb;\n }\n else\n {\n return 128;\n }\n }\n else\n {\n // check for SFX\n if (isValidXGMSB(msb))\n {\n return msb;\n }\n // if lsb is 0 and msb is not, use that\n if (lsb === 0 && msb !== 0)\n {\n return msb;\n }\n if (!isValidXGMSB(lsb))\n {\n return lsb;\n }\n return 0;\n }\n }\n else\n {\n return isDrums ? 128 : msb;\n }\n}\n\n/**\n * @param system {SynthSystem}\n * @returns boolean\n */\nexport function isSystemXG(system)\n{\n return system === \"gm2\" || system === \"xg\";\n}", "import { SYNTHESIZER_GAIN } from \"../../main_processor.js\";\n\n/**\n * @enum {number}\n */\nexport const masterParameterType = {\n mainVolume: 0,\n masterPan: 1,\n voicesCap: 2,\n interpolationType: 3,\n midiSystem: 4\n};\n\n/**\n * @this {SpessaSynthProcessor}\n * @param type {masterParameterType}\n * @param value {number|string|interpolationTypes}\n */\nexport function setMasterParameter(type, value)\n{\n switch (type)\n {\n case masterParameterType.masterPan:\n let pan = value;\n this.pan = pan;\n // clamp to 0-1 (0 is left)\n pan = (pan / 2) + 0.5;\n this.panLeft = (1 - pan);\n this.panRight = (pan);\n break;\n \n case masterParameterType.mainVolume:\n this.masterGain = value * SYNTHESIZER_GAIN;\n this.setMasterParameter(masterParameterType.masterPan, this.pan);\n break;\n \n case masterParameterType.voicesCap:\n this.voiceCap = value;\n break;\n \n case masterParameterType.interpolationType:\n this.interpolationType = value;\n break;\n \n case masterParameterType.midiSystem:\n this.setSystem(value);\n }\n}", "import { IndexedByteArray } from \"../indexed_array.js\";\n\n/**\n * @param dataArray {IndexedByteArray}\n * @param bytes {number}\n * @param encoding {string} the textElement encoding\n * @param trimEnd {boolean} if we should trim once we reach an invalid byte\n * @returns {string}\n */\nexport function readBytesAsString(dataArray, bytes, encoding = undefined, trimEnd = true)\n{\n if (!encoding)\n {\n let finished = false;\n let string = \"\";\n for (let i = 0; i < bytes; i++)\n {\n let byte = dataArray[dataArray.currentIndex++];\n if (finished)\n {\n continue;\n }\n if ((byte < 32 || byte > 127) && byte !== 10) // 10 is \"\\n\"\n {\n if (trimEnd)\n {\n finished = true;\n continue;\n }\n else\n {\n if (byte === 0)\n {\n finished = true;\n continue;\n }\n }\n }\n string += String.fromCharCode(byte);\n }\n return string;\n }\n else\n {\n let byteBuffer = dataArray.slice(dataArray.currentIndex, dataArray.currentIndex + bytes);\n dataArray.currentIndex += bytes;\n let decoder = new TextDecoder(encoding.replace(/[^\\x20-\\x7E]/g, \"\"));\n return decoder.decode(byteBuffer.buffer);\n }\n}\n\n/**\n * @param string {string}\n * @param padLength {number}\n * @returns {IndexedByteArray}\n */\nexport function getStringBytes(string, padLength = 0)\n{\n let len = string.length;\n if (padLength > 0)\n {\n len = padLength;\n }\n const arr = new IndexedByteArray(len);\n writeStringAsBytes(arr, string, padLength);\n return arr;\n}\n\n/**\n * @param string {string}\n * @returns {IndexedByteArray}\n */\nexport function getStringBytesZero(string)\n{\n return getStringBytes(string, string.length + 1);\n}\n\n/**\n * @param string {string}\n * @param outArray {IndexedByteArray}\n * @param padLength {number}\n * @returns {IndexedByteArray} modified IN PLACE\n */\nexport function writeStringAsBytes(outArray, string, padLength = 0)\n{\n if (padLength > 0)\n {\n if (string.length > padLength)\n {\n string = string.slice(0, padLength);\n }\n }\n for (let i = 0; i < string.length; i++)\n {\n outArray[outArray.currentIndex++] = string.charCodeAt(i);\n }\n \n // pad with zeros if needed\n if (padLength > string.length)\n {\n for (let i = 0; i < padLength - string.length; i++)\n {\n outArray[outArray.currentIndex++] = 0;\n }\n }\n return outArray;\n}", "/**\n *\n * @enum {number}\n */\nexport const interpolationTypes = {\n linear: 0,\n nearestNeighbor: 1,\n fourthOrder: 2\n};\n/**\n * The text types for the synth display\n * @enum {number}\n */\nexport const synthDisplayTypes = {\n SoundCanvasText: 0,\n XGText: 1,\n SoundCanvasDotDisplay: 2\n};", "import { arrayToHexString, consoleColors } from \"../../../utils/other.js\";\nimport { SpessaSynthInfo, SpessaSynthWarn } from \"../../../utils/loggin.js\";\nimport { midiControllers } from \"../../../midi/midi_message.js\";\nimport { ALL_CHANNELS_OR_DIFFERENT_ACTION } from \"../../synth_constants.js\";\nimport { isSystemXG } from \"../../../utils/xg_hacks.js\";\nimport { masterParameterType } from \"./controller_control/master_parameters.js\";\nimport { readBytesAsString } from \"../../../utils/byte_functions/string.js\";\nimport { synthDisplayTypes } from \"../engine_components/enums.js\";\n\n/**\n * KeyNum: tuning\n * @typedef {MTSNoteTuning[]} MTSProgramTuning\n */\n\n/**\n * @typedef {Object} MTSNoteTuning\n * @property {number} midiNote - the base midi note to use, -1 means no change\n * @property {number} centTuning - additional tuning\n */\n\n/**\n * Calculates freqency for MIDI Tuning Standard\n * @param byte1 {number}\n * @param byte2 {number}\n * @param byte3 {number}\n * @return {{midiNote: number, centTuning: number|null}}\n */\nfunction getTuning(byte1, byte2, byte3)\n{\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 {\n return { midiNote: -1, centTuning: null };\n }\n \n // calculate cent tuning\n return { midiNote: midiNote, centTuning: fraction * 0.0061 };\n}\n\n\n/**\n * Executes a system exclusive\n * @param messageData {number[]|IndexedByteArray} - the message data without f0\n * @param channelOffset {number}\n * @this {SpessaSynthProcessor}\n */\nexport function systemExclusive(messageData, channelOffset = 0)\n{\n const type = messageData[0];\n if (this.deviceID !== ALL_CHANNELS_OR_DIFFERENT_ACTION && messageData[1] !== 0x7F)\n {\n if (this.deviceID !== messageData[1])\n {\n // not our device ID\n return;\n }\n }\n switch (type)\n {\n default:\n SpessaSynthWarn(\n `%cUnrecognized SysEx: %c${arrayToHexString(messageData)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n break;\n \n // non realtime\n case 0x7E:\n case 0x7F:\n switch (messageData[2])\n {\n case 0x04:\n let cents;\n // device control\n switch (messageData[3])\n {\n case 0x01:\n // main volume\n const vol = messageData[5] << 7 | messageData[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 case 0x02:\n // main balance\n // midi spec page 62\n const balance = messageData[5] << 7 | messageData[4];\n const pan = (balance - 8192) / 8192;\n this.setMasterParameter(masterParameterType.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 = ((messageData[5] << 7) | messageData[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 case 0x04:\n // coarse tuning\n // lsb is ignored\n const semitones = messageData[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 default:\n SpessaSynthWarn(\n `%cUnrecognized MIDI Device Control Real-time message: %c${arrayToHexString(messageData)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n break;\n \n case 0x09:\n // gm system related\n if (messageData[3] === 0x01)\n {\n SpessaSynthInfo(\"%cGM1 system on\", consoleColors.info);\n this.setSystem(\"gm\");\n }\n else if (messageData[3] === 0x03)\n {\n SpessaSynthInfo(\"%cGM2 system on\", consoleColors.info);\n this.setSystem(\"gm2\");\n }\n else\n {\n SpessaSynthInfo(\"%cGM system off, defaulting to GS\", consoleColors.info);\n this.setSystem(\"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 (messageData[3])\n {\n // bulk tuning dump: all 128 notes\n case 0x01:\n const program = messageData[currentMessageIndex++];\n // read the name\n messageData.currentIndex = currentMessageIndex;\n const tuningName = readBytesAsString(messageData, 16);\n currentMessageIndex += 16;\n if (messageData.length < 384)\n {\n SpessaSynthWarn(`The Bulk Tuning Dump is too short! (${messageData.length} bytes, at least 384 are expected)`);\n return;\n }\n // 128 frequencies follow\n for (let i = 0; i < 128; i++)\n {\n // set the given tuning to the program\n this.tunings[program][i] = getTuning(\n messageData[currentMessageIndex++],\n messageData[currentMessageIndex++],\n messageData[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 // single note change\n // single note change bank\n case 0x02:\n case 0x07:\n if (messageData[3] === 0x07)\n {\n // skip the bank\n currentMessageIndex++;\n }\n // get program and number of changes\n const tuningProgram = messageData[currentMessageIndex++];\n const numberOfChanges = messageData[currentMessageIndex++];\n for (let i = 0; i < numberOfChanges; i++)\n {\n // set the given tuning to the program\n this.tunings[tuningProgram][messageData[currentMessageIndex++]] = getTuning(\n messageData[currentMessageIndex++],\n messageData[currentMessageIndex++],\n messageData[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 // 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 (messageData[3] === 0x08)\n {\n // 1 byte tuning: 0 is -64 cents, 64 is 0, 127 is +63\n for (let i = 0; i < 12; i++)\n {\n newOctaveTuning[i] = messageData[7 + i] - 64;\n }\n }\n else\n {\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 {\n const tuning = ((messageData[7 + i] << 7) | messageData[8 + i]) - 8192;\n newOctaveTuning[i / 2] = Math.floor(tuning / 81.92); // map to [-100;+99] cents\n }\n }\n // apply to channels (ordered from 0)\n // bit 1: 14 and 15\n if ((messageData[4] & 1) === 1)\n {\n this.midiAudioChannels[14 + channelOffset].setOctaveTuning(newOctaveTuning);\n }\n if (((messageData[4] >> 1) & 1) === 1)\n {\n this.midiAudioChannels[15 + channelOffset].setOctaveTuning(newOctaveTuning);\n }\n \n // bit 2: channels 7 to 13\n for (let i = 0; i < 7; i++)\n {\n const bit = (messageData[5] >> i) & 1;\n if (bit === 1)\n {\n this.midiAudioChannels[7 + i + channelOffset].setOctaveTuning(newOctaveTuning);\n }\n }\n \n // bit 3: channels 0 to 16\n for (let i = 0; i < 7; i++)\n {\n const bit = (messageData[6] >> i) & 1;\n if (bit === 1)\n {\n this.midiAudioChannels[i + channelOffset].setOctaveTuning(newOctaveTuning);\n }\n }\n \n SpessaSynthInfo(\n `%cMIDI Octave Scale ${\n messageData[3] === 0x08 ? \"(1 byte)\" : \"(2 bytes)\"\n } tuning via Tuning: %c${newOctaveTuning.join(\" \")}`,\n consoleColors.info,\n consoleColors.value\n );\n break;\n \n default:\n SpessaSynthWarn(\n `%cUnrecognized MIDI Tuning standard message: %c${arrayToHexString(messageData)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n break;\n }\n break;\n \n default:\n SpessaSynthWarn(\n `%cUnrecognized MIDI Realtime/non realtime message: %c${arrayToHexString(messageData)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\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 \n function notRecognized()\n {\n // this is some other GS sysex...\n SpessaSynthWarn(\n `%cUnrecognized Roland %cGS %cSysEx: %c${arrayToHexString(messageData)}`,\n consoleColors.warn,\n consoleColors.recognized,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n \n if (messageData[2] === 0x42 && messageData[3] === 0x12)\n {\n // this is a GS sysex\n // messageData[5] and [6] is the system parameter, messageData[7] is the value\n const messageValue = messageData[7];\n if (messageData[6] === 0x7F)\n {\n // GS mode set\n if (messageValue === 0x00)\n {\n // this is a GS reset\n SpessaSynthInfo(\"%cGS Reset received!\", consoleColors.info);\n this.resetAllControllers(false);\n this.setSystem(\"gs\");\n }\n else if (messageValue === 0x7F)\n {\n // GS mode off\n SpessaSynthInfo(\"%cGS system off, switching to GM2\", consoleColors.info);\n this.resetAllControllers(false);\n this.setSystem(\"gm2\");\n }\n return;\n }\n else if (messageData[4] === 0x40)\n {\n // this is a system parameter\n if ((messageData[5] & 0x10) > 0)\n {\n // this is an individual part (channel) parameter\n // determine the channel 0 means channel 10 (default), 1 means 1 etc.\n const channel = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15][messageData[5] & 0x0F] + channelOffset;\n // for example, 0x1A means A = 11, which corresponds to channel 12 (counting from 1)\n const channelObject = this.midiAudioChannels[channel];\n switch (messageData[6])\n {\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 = messageValue > 0 && messageData[5] >> 4; // if set to other than 0, is a drum channel\n channelObject.setDrums(isDrums);\n SpessaSynthInfo(\n `%cChannel %c${channel}%c ${isDrums ?\n \"is now a drum channel\"\n :\n \"now isn't a drum channel\"\n }%c via: %c${arrayToHexString(messageData)}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.value\n );\n return;\n \n case 0x16:\n // this is the pitch key shift sysex\n const keyShift = messageValue - 64;\n channelObject.transposeChannel(keyShift);\n SpessaSynthInfo(\n `%cChannel %c${channel}%c pitch shift. Semitones %c${keyShift}%c, with %c${arrayToHexString(\n messageData)}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n return;\n \n // pan position\n case 0x1C:\n // 0 is random\n let panpot = messageValue;\n if (panpot === 0)\n {\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 }\n else\n {\n channelObject.randomPan = false;\n channelObject.controllerChange(midiControllers.pan, panpot);\n }\n break;\n \n // chorus send\n case 0x21:\n channelObject.controllerChange(midiControllers.chorusDepth, messageValue);\n break;\n \n // reverb send\n case 0x22:\n channelObject.controllerChange(midiControllers.reverbDepth, messageValue);\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 = messageData.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 {\n newTuning[i] = messageData[i + 7] - 64;\n }\n channelObject.setOctaveTuning(newTuning);\n const cents = messageValue - 64;\n SpessaSynthInfo(\n `%cChannel %c${channel}%c octave scale tuning. Cents %c${newTuning.join(\n \" \")}%c, with %c${arrayToHexString(messageData)}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n channelObject.setTuning(cents);\n break;\n }\n return;\n }\n else\n // this is a global system parameter\n if (messageData[5] === 0x00 && messageData[6] === 0x06)\n {\n // roland master pan\n SpessaSynthInfo(\n `%cRoland GS Master Pan set to: %c${messageValue}%c with: %c${arrayToHexString(\n messageData)}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n this.setMasterParameter(masterParameterType.masterPan, (messageValue - 64) / 64);\n return;\n }\n else if (messageData[5] === 0x00 && messageData[6] === 0x05)\n {\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 messageData)}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n this.setMasterTuning(transpose * 100);\n return;\n }\n else if (messageData[5] === 0x00 && messageData[6] === 0x04)\n {\n // roland GS master volume\n SpessaSynthInfo(\n `%cRoland GS Master Volume set to: %c${messageValue}%c with: %c${arrayToHexString(\n messageData)}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n this.setMIDIVolume(messageValue / 127);\n return;\n }\n }\n // this is some other GS sysex...\n notRecognized();\n return;\n }\n else if (messageData[2] === 0x45 && messageData[3] === 0x12)\n {\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 messageData[4] === 0x10 && // Sound Canvas Display\n messageData[6] === 0x00 // Data follows\n )\n {\n if (messageData[5] === 0x00) // Display letters\n {\n // get the text\n // and header ends with (checksum) F7\n const text = new Uint8Array(messageData.slice(7, messageData.length - 2));\n this.callEvent(\n \"synthdisplay\",\n {\n displayData: text,\n displayType: synthDisplayTypes.SoundCanvasText\n }\n );\n }\n else if (messageData[5] === 0x01) // Matrix display\n {\n // get the data\n // and header ends with (checksum) F7\n const dotMatrixData = new Uint8Array(messageData.slice(7, messageData.length - 3));\n this.callEvent(\n \"synthdisplay\",\n {\n displayData: dotMatrixData,\n displayType: synthDisplayTypes.SoundCanvasDotDisplay\n }\n );\n SpessaSynthInfo(\n `%cRoland SC Display Dot Matrix via: %c${arrayToHexString(\n messageData)}`,\n consoleColors.info,\n consoleColors.value\n );\n }\n else\n {\n // this is some other GS sysex...\n notRecognized();\n }\n }\n }\n else if (messageData[2] === 0x16 && messageData[3] === 0x12 && messageData[4] === 0x10)\n {\n // this is a roland master volume message\n this.setMIDIVolume(messageData[7] / 100);\n SpessaSynthInfo(\n `%cRoland Master Volume control set to: %c${messageData[7]}%c via: %c${arrayToHexString(\n messageData)}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n return;\n }\n else\n {\n // this is something else...\n SpessaSynthWarn(\n `%cUnrecognized Roland SysEx: %c${arrayToHexString(messageData)}`,\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 (messageData[2] === 0x4C)\n {\n // XG system parameter\n if (messageData[3] === 0x00 && messageData[4] === 0x00)\n {\n switch (messageData[5])\n {\n // master volume\n case 0x04:\n const vol = messageData[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 // master transpose\n case 0x06:\n const transpose = messageData[6] - 64;\n this.transposeAllChannels(transpose);\n SpessaSynthInfo(\n `%cXG master transpose. Volume: %c${transpose}`,\n consoleColors.info,\n consoleColors.recognized\n );\n break;\n \n // XG on\n case 0x7E:\n SpessaSynthInfo(\"%cXG system on\", consoleColors.info);\n this.resetAllControllers(false);\n this.setSystem(\"xg\");\n break;\n }\n }\n else\n // XG part parameter\n if (messageData[3] === 0x08)\n {\n if (!isSystemXG(this.system))\n {\n return;\n }\n const channel = messageData[4] + channelOffset;\n if (channel >= this.midiAudioChannels.length)\n {\n // invalid channel\n return;\n }\n const channelObject = this.midiAudioChannels[channel];\n const value = messageData[6];\n switch (messageData[5])\n {\n // bank-select MSB\n case 0x01:\n channelObject.controllerChange(midiControllers.bankSelect, value);\n break;\n \n // bank-select LSB\n case 0x02:\n channelObject.controllerChange(midiControllers.lsbForControl0BankSelect, value);\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 {\n return;\n }\n const semitones = value - 64;\n channelObject.channelTransposeKeyShift = semitones;\n break;\n \n // volume\n case 0x0B:\n channelObject.controllerChange(midiControllers.mainVolume, value);\n break;\n \n // pan position\n case 0x0E:\n let pan = value;\n if (pan === 0)\n {\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 }\n else\n {\n channelObject.controllerChange(midiControllers.pan, pan);\n }\n break;\n \n // reverb\n case 0x13:\n channelObject.controllerChange(midiControllers.reverbDepth, value);\n break;\n \n // chorus\n case 0x12:\n channelObject.controllerChange(midiControllers.chorusDepth, value);\n break;\n \n default:\n SpessaSynthWarn(\n `%cUnrecognized Yamaha XG Part Setup: %c${messageData[5].toString(16)\n .toUpperCase()}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n }\n else if (\n messageData[3] === 0x06 && // XG System parameter\n messageData[4] === 0x00 // System Byte\n )\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(messageData.slice(5, messageData.length - 1));\n this.callEvent(\n \"synthdisplay\",\n {\n displayData: textData,\n displayType: synthDisplayTypes.XGText\n }\n );\n }\n else if (isSystemXG(this.system))\n {\n SpessaSynthWarn(\n `%cUnrecognized Yamaha XG SysEx: %c${arrayToHexString(messageData)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n \n }\n else\n {\n if (isSystemXG(this.system))\n {\n SpessaSynthWarn(\n `%cUnrecognized Yamaha SysEx: %c${arrayToHexString(messageData)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n }\n break;\n \n \n }\n}", "import { generatorTypes } from \"./generator.js\";\nimport { midiControllers } from \"../../midi/midi_message.js\";\n\n/**\n * modulators.js\n * purpose: parses soundfont modulators and the source enums, also includes the default modulators list\n **/\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 \n};\nexport const modulatorCurveTypes = {\n linear: 0,\n concave: 1,\n convex: 2,\n switch: 3\n};\n\nexport class Modulator\n{\n /**\n * The current computed value of this modulator\n * @type {number}\n */\n currentValue = 0;\n \n /**\n * The source enumeration for this modulator\n * @type {number}\n */\n sourceEnum;\n \n /**\n * The secondary source enumeration for this modulator\n * @type {number}\n */\n secondarySourceEnum;\n \n /**\n * The generator destination of this modulator\n * @type {generatorTypes}\n */\n modulatorDestination;\n \n /**\n * The transform amount for this modulator\n * @type {number}\n */\n transformAmount;\n \n /**\n * The transform type for this modulator\n * @type {0|2}\n */\n transformType;\n \n /**\n * creates a modulator\n * @param srcEnum {number}\n * @param secSrcEnum {number}\n * @param destination {generatorTypes|number}\n * @param amount {number}\n * @param transformType {number}\n */\n constructor(srcEnum, secSrcEnum, destination, amount, transformType)\n {\n this.sourceEnum = srcEnum;\n this.modulatorDestination = destination;\n this.secondarySourceEnum = secSrcEnum;\n this.transformAmount = amount;\n this.transformType = transformType;\n \n \n if (this.modulatorDestination > 58)\n {\n this.modulatorDestination = generatorTypes.INVALID; // flag as invalid (for linked ones)\n }\n \n // decode the source\n this.sourcePolarity = this.sourceEnum >> 9 & 1;\n this.sourceDirection = this.sourceEnum >> 8 & 1;\n this.sourceUsesCC = this.sourceEnum >> 7 & 1;\n this.sourceIndex = this.sourceEnum & 127;\n this.sourceCurveType = this.sourceEnum >> 10 & 3;\n \n // decode the secondary source\n this.secSrcPolarity = this.secondarySourceEnum >> 9 & 1;\n this.secSrcDirection = this.secondarySourceEnum >> 8 & 1;\n this.secSrcUsesCC = this.secondarySourceEnum >> 7 & 1;\n this.secSrcIndex = this.secondarySourceEnum & 127;\n this.secSrcCurveType = this.secondarySourceEnum >> 10 & 3;\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 * @type {boolean}\n */\n this.isEffectModulator =\n (\n this.sourceEnum === 0x00DB\n || this.sourceEnum === 0x00DD\n )\n && this.secondarySourceEnum === 0x0\n && (\n this.modulatorDestination === generatorTypes.reverbEffectsSend\n || this.modulatorDestination === generatorTypes.chorusEffectsSend\n );\n }\n \n /**\n * @param modulator {Modulator}\n * @returns {Modulator}\n */\n static copy(modulator)\n {\n return new Modulator(\n modulator.sourceEnum,\n modulator.secondarySourceEnum,\n modulator.modulatorDestination,\n modulator.transformAmount,\n modulator.transformType\n );\n }\n \n /**\n * @param mod1 {Modulator}\n * @param mod2 {Modulator}\n * @param checkAmount {boolean}\n * @returns {boolean}\n */\n static isIdentical(mod1, mod2, checkAmount = false)\n {\n return (mod1.sourceEnum === mod2.sourceEnum)\n && (mod1.modulatorDestination === mod2.modulatorDestination)\n && (mod1.secondarySourceEnum === mod2.secondarySourceEnum)\n && (mod1.transformType === mod2.transformType)\n && (!checkAmount || (mod1.transformAmount === mod2.transformAmount));\n }\n \n /**\n * @param mod {Modulator}\n * @returns {string}\n */\n static debugString(mod)\n {\n function getKeyByValue(object, value)\n {\n return Object.keys(object).find(key => object[key] === value);\n }\n \n let sourceString = getKeyByValue(modulatorCurveTypes, mod.sourceCurveType);\n sourceString += mod.sourcePolarity === 0 ? \" unipolar \" : \" bipolar \";\n sourceString += mod.sourceDirection === 0 ? \"forwards \" : \"backwards \";\n if (mod.sourceUsesCC)\n {\n sourceString += getKeyByValue(midiControllers, mod.sourceIndex);\n }\n else\n {\n sourceString += getKeyByValue(modulatorSources, mod.sourceIndex);\n }\n \n let secSrcString = getKeyByValue(modulatorCurveTypes, mod.secSrcCurveType);\n secSrcString += mod.secSrcPolarity === 0 ? \" unipolar \" : \" bipolar \";\n secSrcString += mod.secSrcCurveType === 0 ? \"forwards \" : \"backwards \";\n if (mod.secSrcUsesCC)\n {\n secSrcString += getKeyByValue(midiControllers, mod.secSrcIndex);\n }\n else\n {\n secSrcString += getKeyByValue(modulatorSources, mod.secSrcIndex);\n }\n return `Modulator:\n Source: ${sourceString}\n Secondary source: ${secSrcString}\n Destination: ${getKeyByValue(generatorTypes, mod.modulatorDestination)}\n Trasform amount: ${mod.transformAmount}\n Transform type: ${mod.transformType}\n \\n\\n`;\n }\n \n /**\n * Sum transform and create a NEW modulator\n * @param modulator {Modulator}\n * @returns {Modulator}\n */\n sumTransform(modulator)\n {\n return new Modulator(\n this.sourceEnum,\n this.secondarySourceEnum,\n this.modulatorDestination,\n this.transformAmount + modulator.transformAmount,\n this.transformType\n );\n }\n}\n\nexport const DEFAULT_ATTENUATION_MOD_AMOUNT = 960;\nexport const DEFAULT_ATTENUATION_MOD_CURVE_TYPE = modulatorCurveTypes.concave;\n\nexport function getModSourceEnum(curveType, polarity, direction, isCC, index)\n{\n return (curveType << 10) | (polarity << 9) | (direction << 8) | (isCC << 7) | index;\n}\n\nconst soundFontModulators = [\n // vel to attenuation\n new Modulator(\n getModSourceEnum(\n DEFAULT_ATTENUATION_MOD_CURVE_TYPE,\n 0,\n 1,\n 0,\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 Modulator(0x0081, 0x0, generatorTypes.vibLfoToPitch, 50, 0),\n \n // vol to attenuation\n new Modulator(\n getModSourceEnum(\n DEFAULT_ATTENUATION_MOD_CURVE_TYPE,\n 0,\n 1,\n 1,\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 Modulator(0x000D, 0x0, generatorTypes.vibLfoToPitch, 50, 0),\n \n // pitch wheel to tuning\n new Modulator(0x020E, 0x0010, generatorTypes.fineTune, 12700, 0),\n \n // pan to uhh, pan\n // amount is 500 instead of 1000, see #59\n new Modulator(0x028A, 0x0, generatorTypes.pan, 500, 0),\n \n // expression to attenuation\n new Modulator(\n getModSourceEnum(\n DEFAULT_ATTENUATION_MOD_CURVE_TYPE,\n 0,\n 1,\n 1,\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 Modulator(0x00DB, 0x0, generatorTypes.reverbEffectsSend, 200, 0),\n \n // chorus effects to send\n new Modulator(0x00DD, 0x0, generatorTypes.chorusEffectsSend, 200, 0)\n];\n\nconst customModulators = [\n // custom modulators heck yeah\n // poly pressure to vibrato\n new Modulator(\n getModSourceEnum(modulatorCurveTypes.linear, 0, 0, 0, modulatorSources.polyPressure),\n 0x0,\n generatorTypes.vibLfoToPitch,\n 50,\n 0\n ),\n \n // cc 92 (tremolo) to modLFO volume\n new Modulator(\n getModSourceEnum(\n modulatorCurveTypes.linear,\n 0,\n 0,\n 1,\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 Modulator(\n getModSourceEnum(\n modulatorCurveTypes.convex,\n 1,\n 0,\n 1,\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 Modulator(\n getModSourceEnum(\n modulatorCurveTypes.linear,\n 1,\n 0,\n 1,\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 Modulator(\n getModSourceEnum(\n modulatorCurveTypes.linear,\n 1,\n 0,\n 1,\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\n new Modulator(\n getModSourceEnum(\n modulatorCurveTypes.linear,\n 1,\n 0,\n 1,\n midiControllers.filterResonance\n ), // linear forwards bipolar cc 74\n 0x0, // no controller\n generatorTypes.initialFilterQ,\n 250,\n 0\n )\n];\n\n/**\n * @type {Modulator[]}\n */\nexport const defaultModulators = soundFontModulators.concat(customModulators);", "import { midiControllers } from \"../../../midi/midi_message.js\";\nimport { modulatorSources } from \"../../../soundfont/basic_soundfont/modulator.js\";\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 preset default values, so we can quickly use set() to reset the controllers\nexport const resetArray = new Int16Array(CONTROLLER_TABLE_SIZE).fill(0);\nexport const setResetValue = (i, v) => resetArray[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.RPNLsb, 127);\nsetResetValue(midiControllers.RPNMsb, 127);\nsetResetValue(midiControllers.NRPNLsb, 127);\nsetResetValue(midiControllers.NRPNMsb, 127);\n\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.\nresetArray[midiControllers.portamentoControl] = PORTAMENTO_CONTROL_UNSET;\n\n// pitch wheel\nsetResetValue(NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel, 64);\nsetResetValue(NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange, 2);\n\n/**\n * @enum {number}\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};\nexport const CUSTOM_CONTROLLER_TABLE_SIZE = Object.keys(customControllers).length;\nexport const customResetArray = new Float32Array(CUSTOM_CONTROLLER_TABLE_SIZE);\ncustomResetArray[customControllers.modulationMultiplier] = 1;\n/**\n * @enum {number}\n */\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};\n/**\n * This is a channel configuration enum, it is internally sent from Synthetizer via controller change\n * @enum {number}\n */\nexport const channelConfiguration = {\n velocityOverride: 128 // overrides velocity for the given channel\n};", "import { consoleColors } from \"../../../../utils/other.js\";\nimport { SpessaSynthInfo } from \"../../../../utils/loggin.js\";\nimport { modulatorSources } from \"../../../../soundfont/basic_soundfont/modulator.js\";\nimport {\n customControllers,\n customResetArray,\n dataEntryStates,\n NON_CC_INDEX_OFFSET,\n PORTAMENTO_CONTROL_UNSET,\n resetArray\n} from \"../../engine_components/controller_tables.js\";\nimport { midiControllers } from \"../../../../midi/midi_message.js\";\nimport { DEFAULT_PERCUSSION, DEFAULT_SYNTH_MODE } from \"../../../synth_constants.js\";\nimport { getDefaultBank } from \"../../../../utils/xg_hacks.js\";\n\n\n/**\n * Full system reset\n * @this {SpessaSynthProcessor}\n * @param log {boolean}\n */\nexport function resetAllControllers(log = true)\n{\n if (log)\n {\n SpessaSynthInfo(\"%cResetting all controllers!\", consoleColors.info);\n }\n this.callEvent(\"allcontrollerreset\", undefined);\n this.setSystem(DEFAULT_SYNTH_MODE);\n for (let channelNumber = 0; channelNumber < this.midiAudioChannels.length; channelNumber++)\n {\n this.midiAudioChannels[channelNumber].resetControllers();\n \n /**\n * @type {MidiAudioChannel}\n **/\n const ch = this.midiAudioChannels[channelNumber];\n \n // if preset is unlocked, switch to non-drums and call event\n if (!ch.lockPreset)\n {\n ch.setBankSelect(getDefaultBank(this.system));\n if (channelNumber % 16 === DEFAULT_PERCUSSION)\n {\n ch.setPreset(this.drumPreset);\n ch.presetUsesOverride = this.defaultDrumsUsesOverride;\n ch.drumChannel = true;\n this.callEvent(\"drumchange\", {\n channel: channelNumber,\n isDrumChannel: true\n });\n }\n else\n {\n ch.drumChannel = false;\n ch.presetUsesOverride = this.defaultDrumsUsesOverride;\n ch.setPreset(this.defaultPreset);\n this.callEvent(\"drumchange\", {\n channel: channelNumber,\n isDrumChannel: false\n });\n }\n }\n else\n {\n this.callEvent(\"drumchange\", {\n channel: channelNumber,\n isDrumChannel: ch.drumChannel\n });\n }\n \n const presetBank = ch.preset.bank;\n const sentBank = presetBank === 128 ? 128 : (ch.presetUsesOverride ? presetBank + this.soundfontBankOffset : presetBank);\n \n // call program change\n this.callEvent(\"programchange\", {\n channel: channelNumber,\n program: ch.preset.program,\n bank: sentBank\n });\n \n for (let ccNum = 0; ccNum < 128; ccNum++)\n {\n if (this.midiAudioChannels[channelNumber].lockedControllers[ccNum])\n {\n // was not reset so restore the value\n this.callEvent(\"controllerchange\", {\n channel: channelNumber,\n controllerNumber: ccNum,\n controllerValue: this.midiAudioChannels[channelNumber].midiControllers[ccNum] >> 7\n });\n }\n \n }\n \n \n // restore pitch wheel\n if (this.midiAudioChannels[channelNumber].lockedControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel] === false)\n {\n const val = this.midiAudioChannels[channelNumber].midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel];\n const msb = val >> 7;\n const lsb = val & 0x7F;\n this.callEvent(\"pitchwheel\", {\n channel: channelNumber,\n MSB: msb,\n LSB: lsb\n });\n }\n }\n this.tunings = [];\n this.tunings = [];\n for (let i = 0; i < 128; i++)\n {\n this.tunings.push([]);\n }\n \n this.setMIDIVolume(1);\n}\n\n/**\n * Resets all controllers for channel\n * @this {MidiAudioChannel}\n */\nexport function resetControllers()\n{\n this.channelOctaveTuning.fill(0);\n \n // reset the array\n for (let i = 0; i < resetArray.length; i++)\n {\n if (this.lockedControllers[i])\n {\n continue;\n }\n const resetValue = resetArray[i];\n if (this.midiControllers[i] !== resetValue && i < 127)\n {\n if (i === midiControllers.portamentoControl)\n {\n this.midiControllers[i] = PORTAMENTO_CONTROL_UNSET;\n }\n else\n {\n this.controllerChange(i, resetValue >> 7);\n }\n }\n else\n {\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.holdPedal = false;\n this.randomPan = false;\n \n // reset custom controllers\n // special case: transpose does not get affected\n const transpose = this.customControllers[customControllers.channelTransposeFine];\n this.customControllers.set(customResetArray);\n this.setCustomController(customControllers.channelTransposeFine, transpose);\n \n this.resetParameters();\n \n}\n\n\n/**\n * @type {Set<midiControllers|number>}\n */\nexport const nonResetableCCs = new Set([\n midiControllers.bankSelect,\n midiControllers.lsbForControl0BankSelect,\n midiControllers.mainVolume,\n midiControllers.lsbForControl7MainVolume,\n midiControllers.pan,\n midiControllers.lsbForControl10Pan,\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]);\n\n/**\n * Reset all controllers for channel, but RP-15 compliant\n * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf\n * @this {MidiAudioChannel}\n */\nexport function resetControllersRP15Compliant()\n{\n // reset tunings\n this.channelOctaveTuning.fill(0);\n \n // reset pitch bend\n this.pitchWheel(64, 0);\n \n this.channelVibrato = { rate: 0, depth: 0, delay: 0 };\n \n for (let i = 0; i < 128; i++)\n {\n const resetValue = resetArray[i];\n if (!nonResetableCCs.has(i) && resetValue !== this.midiControllers[i])\n {\n if (i === midiControllers.portamentoControl)\n {\n this.midiControllers[i] = PORTAMENTO_CONTROL_UNSET;\n }\n else\n {\n this.controllerChange(i, resetValue >> 7);\n }\n }\n }\n}\n\n/**\n * @this {MidiAudioChannel}\n */\nexport function resetParameters()\n{\n /**\n * reset the state machine to idle\n * @type {string}\n */\n this.dataEntryState = dataEntryStates.Idle;\n SpessaSynthInfo(\n \"%cResetting Registered and Non-Registered Parameters!\",\n consoleColors.info\n );\n}", "/**\n * Reads as little endian\n * @param dataArray {IndexedByteArray}\n * @param bytesAmount {number}\n * @returns {number}\n */\nexport function readLittleEndian(dataArray, bytesAmount)\n{\n let out = 0;\n for (let i = 0; i < bytesAmount; i++)\n {\n out |= (dataArray[dataArray.currentIndex++] << 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 {IndexedByteArray}\n * @param number {number}\n * @param byteTarget {number}\n */\nexport function writeLittleEndian(dataArray, number, byteTarget)\n{\n for (let i = 0; i < byteTarget; i++)\n {\n dataArray[dataArray.currentIndex++] = (number >> (i * 8)) & 0xFF;\n }\n}\n\n/**\n * @param dataArray {IndexedByteArray}\n * @param word {number}\n */\nexport function writeWord(dataArray, word)\n{\n dataArray[dataArray.currentIndex++] = word & 0xFF;\n dataArray[dataArray.currentIndex++] = word >> 8;\n}\n\n/**\n * @param dataArray {IndexedByteArray}\n * @param dword {number}\n */\nexport function writeDword(dataArray, dword)\n{\n writeLittleEndian(dataArray, dword, 4);\n}\n\n/**\n * @param byte1 {number}\n * @param byte2 {number}\n * @returns {number}\n */\nexport function signedInt16(byte1, byte2)\n{\n let val = (byte2 << 8) | byte1;\n if (val > 32767)\n {\n return val - 65536;\n }\n return val;\n}\n\n/**\n * @param byte {number}\n * @returns {number}\n */\nexport function signedInt8(byte)\n{\n if (byte > 127)\n {\n return byte - 256;\n }\n return byte;\n}", "import { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { readLittleEndian, writeDword } from \"../../utils/byte_functions/little_endian.js\";\nimport { readBytesAsString, writeStringAsBytes } from \"../../utils/byte_functions/string.js\";\n\n/**\n * riff_chunk.js\n * reads a riff read and stores it as a class\n */\n\nexport class RiffChunk\n{\n /**\n * Creates a new riff read\n * @constructor\n * @param header {string}\n * @param size {number}\n * @param data {IndexedByteArray}\n */\n constructor(header, size, data)\n {\n this.header = header;\n this.size = size;\n this.chunkData = data;\n }\n \n}\n\n/**\n * @param dataArray {IndexedByteArray}\n * @param readData {boolean}\n * @param forceShift {boolean}\n * @returns {RiffChunk}\n */\nexport function readRIFFChunk(dataArray, readData = true, forceShift = false)\n{\n let header = readBytesAsString(dataArray, 4);\n \n let size = readLittleEndian(dataArray, 4);\n let chunkData = undefined;\n if (readData)\n {\n chunkData = new IndexedByteArray(dataArray.buffer.slice(dataArray.currentIndex, dataArray.currentIndex + size));\n }\n if (readData || forceShift)\n {\n dataArray.currentIndex += size;\n }\n \n if (size % 2 !== 0)\n {\n if (dataArray[dataArray.currentIndex] === 0)\n {\n dataArray.currentIndex++;\n }\n }\n \n return new RiffChunk(header, size, chunkData);\n}\n\n/**\n * @param chunk {RiffChunk}\n * @param prepend {IndexedByteArray}\n * @returns {IndexedByteArray}\n */\nexport function writeRIFFChunk(chunk, prepend = undefined)\n{\n let size = 8 + chunk.size;\n if (chunk.size % 2 !== 0)\n {\n size++;\n }\n if (prepend)\n {\n size += prepend.length;\n }\n const array = new IndexedByteArray(size);\n // prepend data (for example, type before the read)\n if (prepend)\n {\n array.set(prepend, array.currentIndex);\n array.currentIndex += prepend.length;\n }\n // write header\n writeStringAsBytes(array, chunk.header);\n // write size (excluding header and the size itself) and then prepend if specified\n writeDword(array, size - 8 - (prepend?.length || 0));\n // write data\n array.set(chunk.chunkData, array.currentIndex);\n return array;\n}\n\n/**\n * @param header {string}\n * @param data {Uint8Array}\n * @param addZeroByte {Boolean}\n * @param isList {boolean}\n * @returns {IndexedByteArray}\n */\nexport function writeRIFFOddSize(header, data, addZeroByte = false, isList = false)\n{\n if (addZeroByte)\n {\n const tempData = new Uint8Array(data.length + 1);\n tempData.set(data);\n data = tempData;\n }\n let offset = 8;\n let finalSize = offset + data.length;\n let writtenSize = data.length;\n if (finalSize % 2 !== 0)\n {\n finalSize++;\n }\n let headerWritten = header;\n if (isList)\n {\n finalSize += 4;\n writtenSize += 4;\n offset += 4;\n headerWritten = \"LIST\";\n }\n const outArray = new IndexedByteArray(finalSize);\n writeStringAsBytes(outArray, headerWritten);\n writeDword(outArray, writtenSize);\n if (isList)\n {\n writeStringAsBytes(outArray, header);\n }\n outArray.set(data, offset);\n return outArray;\n}\n\n/**\n * @param collection {RiffChunk[]}\n * @param type {string}\n * @returns {RiffChunk|undefined}\n */\nexport function findRIFFListType(collection, type)\n{\n return collection.find(c =>\n {\n if (c.header !== \"LIST\")\n {\n return false;\n }\n c.chunkData.currentIndex = 0;\n return readBytesAsString(c.chunkData, 4) === type;\n });\n}", "import { writeDword, writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\n\nimport { Generator, generatorTypes } from \"../generator.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function getIGEN()\n{\n // go through all instruments -> zones and write generators sequentially (add 4 for terminal)\n let igensize = 4;\n for (const inst of this.instruments)\n {\n igensize += inst.instrumentZones.reduce((sum, z) =>\n {\n // clear sample and range generators before determining the size\n z.generators = z.generators.filter(g =>\n g.generatorType !== generatorTypes.sampleID &&\n g.generatorType !== generatorTypes.keyRange &&\n g.generatorType !== generatorTypes.velRange\n );\n // add sample and ranges if necessary\n // unshift vel then key (to make key first) and the instrument is last\n if (z.velRange.max !== 127 || z.velRange.min !== 0)\n {\n z.generators.unshift(new Generator(\n generatorTypes.velRange,\n z.velRange.max << 8 | Math.max(z.velRange.min, 0),\n false\n ));\n }\n if (z.keyRange.max !== 127 || z.keyRange.min !== 0)\n {\n z.generators.unshift(new Generator(\n generatorTypes.keyRange,\n z.keyRange.max << 8 | Math.max(z.keyRange.min, 0),\n false\n ));\n }\n if (!z.isGlobal)\n {\n // write sample\n z.generators.push(new Generator(\n generatorTypes.sampleID,\n this.samples.indexOf(z.sample),\n false\n ));\n }\n return z.generators.length * 4 + sum;\n }, 0);\n }\n const igendata = new IndexedByteArray(igensize);\n let igenIndex = 0;\n for (const instrument of this.instruments)\n {\n for (const instrumentZone of instrument.instrumentZones)\n {\n // set the start index here\n instrumentZone.generatorZoneStartIndex = igenIndex;\n for (const gen of instrumentZone.generators)\n {\n // name is deceptive, it works on negatives\n writeWord(igendata, gen.generatorType);\n writeWord(igendata, gen.generatorValue);\n igenIndex++;\n }\n }\n }\n // terminal generator, is zero\n writeDword(igendata, 0);\n \n return writeRIFFChunk(new RiffChunk(\n \"igen\",\n igendata.length,\n igendata\n ));\n}", "import { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\nimport { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { SpessaSynthInfo } from \"../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../utils/other.js\";\n\n/**\n * @this {BasicSoundBank}\n * @param smplStartOffsets {number[]}\n * @param smplEndOffsets {number[]}\n * @param compress {boolean}\n * @param quality {number}\n * @param vorbisFunc {EncodeVorbisFunction}\n * @returns {IndexedByteArray}\n */\nexport function getSDTA(smplStartOffsets, smplEndOffsets, compress, quality, vorbisFunc)\n{\n // write smpl: write int16 data of each sample linearly\n // get size (calling getAudioData twice doesn't matter since it gets cached)\n const sampleDatas = this.samples.map((s, i) =>\n {\n if (compress)\n {\n s.compressSample(quality, vorbisFunc);\n }\n const r = s.getRawData();\n SpessaSynthInfo(\n `%cEncoded sample %c${i}. ${s.sampleName}%c of %c${this.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 ? consoleColors.recognized : consoleColors.unrecognized,\n consoleColors.info\n );\n return r;\n });\n const smplSize = this.samples.reduce((total, s, i) =>\n {\n return total + sampleDatas[i].length + 46;\n }, 0);\n const smplData = new IndexedByteArray(smplSize);\n // resample to int16 and write out\n this.samples.forEach((sample, i) =>\n {\n const data = sampleDatas[i];\n let startOffset;\n let endOffset;\n let jump = data.length;\n if (sample.isCompressed)\n {\n // sf3 offset is in bytes\n startOffset = smplData.currentIndex;\n endOffset = startOffset + data.length;\n }\n else\n {\n // sf2 in sample data points\n startOffset = smplData.currentIndex / 2;\n endOffset = startOffset + data.length / 2;\n jump += 46;\n }\n smplStartOffsets.push(startOffset);\n smplData.set(data, smplData.currentIndex);\n smplData.currentIndex += jump;\n smplEndOffsets.push(endOffset);\n });\n \n const smplChunk = writeRIFFChunk(new RiffChunk(\n \"smpl\",\n smplData.length,\n smplData\n ), new IndexedByteArray([115, 100, 116, 97])); // `sdta`\n \n return writeRIFFChunk(new RiffChunk(\n \"LIST\",\n smplChunk.length,\n smplChunk\n ));\n}", "import { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeStringAsBytes } from \"../../../utils/byte_functions/string.js\";\nimport { writeDword, writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\n\n/**\n * @this {BasicSoundBank}\n * @param smplStartOffsets {number[]}\n * @param smplEndOffsets {number[]}\n * @returns {IndexedByteArray}\n */\nexport function getSHDR(smplStartOffsets, smplEndOffsets)\n{\n const sampleLength = 46;\n const shdrData = new IndexedByteArray(sampleLength * (this.samples.length + 1)); // +1 because EOP\n this.samples.forEach((sample, index) =>\n {\n // sample name\n writeStringAsBytes(shdrData, sample.sampleName, 20);\n // start offset\n const dwStart = smplStartOffsets[index];\n writeDword(shdrData, dwStart);\n // end offset\n const dwEnd = smplEndOffsets[index];\n writeDword(shdrData, dwEnd);\n // loop is stored as relative in sample points, change it to absolute sample points here\n let loopStart = sample.sampleLoopStartIndex + dwStart;\n let loopEnd = sample.sampleLoopEndIndex + dwStart;\n if (sample.isCompressed)\n {\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.samplePitch;\n shdrData[shdrData.currentIndex++] = sample.samplePitchCorrection;\n // sample link\n writeWord(shdrData, sample.sampleLink);\n // sample type: write raw because we simply copy compressed samples\n writeWord(shdrData, sample.sampleType);\n });\n \n // write EOS and zero everything else\n writeStringAsBytes(shdrData, \"EOS\", sampleLength);\n return writeRIFFChunk(new RiffChunk(\n \"shdr\",\n shdrData.length,\n shdrData\n ));\n}", "import { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeLittleEndian, writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function getIMOD()\n{\n // very similar to igen,\n // go through all instruments -> zones and write modulators sequentially\n let imodsize = 10;\n for (const inst of this.instruments)\n {\n imodsize += inst.instrumentZones.reduce((sum, z) => z.modulators.length * 10 + sum, 0);\n }\n const imoddata = new IndexedByteArray(imodsize);\n let imodIndex = 0;\n for (const inst of this.instruments)\n {\n for (const ibag of inst.instrumentZones)\n {\n // set the start index here\n ibag.modulatorZoneStartIndex = imodIndex;\n for (const mod of ibag.modulators)\n {\n writeWord(imoddata, mod.sourceEnum);\n writeWord(imoddata, mod.modulatorDestination);\n writeWord(imoddata, mod.transformAmount);\n writeWord(imoddata, mod.secondarySourceEnum);\n writeWord(imoddata, mod.transformType);\n imodIndex++;\n }\n }\n }\n \n // terminal modulator, is zero\n writeLittleEndian(imoddata, 0, 10);\n \n return writeRIFFChunk(new RiffChunk(\n \"imod\",\n imoddata.length,\n imoddata\n ));\n}", "import { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function getIBAG()\n{\n // write all ibag with their start indexes as they were changed in getIGEN() and getIMOD()\n const ibagsize = this.instruments.reduce((sum, i) => i.instrumentZones.length * 4 + sum, 4);\n const ibagdata = new IndexedByteArray(ibagsize);\n let zoneID = 0;\n let generatorIndex = 0;\n let modulatorIndex = 0;\n for (const inst of this.instruments)\n {\n inst.instrumentZoneIndex = zoneID;\n for (const ibag of inst.instrumentZones)\n {\n ibag.zoneID = zoneID;\n writeWord(ibagdata, generatorIndex);\n writeWord(ibagdata, modulatorIndex);\n generatorIndex += ibag.generators.length;\n modulatorIndex += ibag.modulators.length;\n zoneID++;\n }\n }\n // write the terminal IBAG\n writeWord(ibagdata, generatorIndex);\n writeWord(ibagdata, modulatorIndex);\n \n return writeRIFFChunk(new RiffChunk(\n \"ibag\",\n ibagdata.length,\n ibagdata\n ));\n}", "import { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeStringAsBytes } from \"../../../utils/byte_functions/string.js\";\nimport { writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function getINST()\n{\n const instsize = this.instruments.length * 22 + 22;\n const instdata = new IndexedByteArray(instsize);\n // the instrument start index is adjusted in ibag, write it here\n let instrumentStart = 0;\n let instrumentID = 0;\n for (const inst of this.instruments)\n {\n writeStringAsBytes(instdata, inst.instrumentName, 20);\n writeWord(instdata, instrumentStart);\n instrumentStart += inst.instrumentZones.length;\n inst.instrumentID = instrumentID;\n instrumentID++;\n }\n // write EOI\n writeStringAsBytes(instdata, \"EOI\", 20);\n writeWord(instdata, instrumentStart);\n \n return writeRIFFChunk(new RiffChunk(\n \"inst\",\n instdata.length,\n instdata\n ));\n}", "import { writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\n\nimport { Generator, generatorTypes } from \"../generator.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function getPGEN()\n{\n // almost identical to igen, except the correct instrument instead of sample gen\n // goes through all preset zones and writes generators sequentially (add 4 for terminal)\n let pgensize = 4;\n for (const preset of this.presets)\n {\n pgensize += preset.presetZones.reduce((size, z) =>\n {\n // clear instrument and range generators before determining the size\n z.generators = z.generators.filter(g =>\n g.generatorType !== generatorTypes.instrument &&\n g.generatorType !== generatorTypes.keyRange &&\n g.generatorType !== generatorTypes.velRange\n );\n // unshift vel then key and instrument is last\n if (z.velRange.max !== 127 || z.velRange.min !== 0)\n {\n z.generators.unshift(new Generator(\n generatorTypes.velRange,\n z.velRange.max << 8 | Math.max(z.velRange.min, 0),\n false\n ));\n }\n if (z.keyRange.max !== 127 || z.keyRange.min !== 0)\n {\n z.generators.unshift(new Generator(\n generatorTypes.keyRange,\n z.keyRange.max << 8 | Math.max(z.keyRange.min, 0),\n false\n ));\n }\n if (!z.isGlobal)\n {\n // write the instrument\n z.generators.push(new Generator(\n generatorTypes.instrument,\n this.instruments.indexOf(z.instrument),\n false\n ));\n }\n return z.generators.length * 4 + size;\n }, 0);\n }\n const pgendata = new IndexedByteArray(pgensize);\n let pgenIndex = 0;\n for (const preset of this.presets)\n {\n for (const presetZone of preset.presetZones)\n {\n // set the start index here\n presetZone.generatorZoneStartIndex = pgenIndex;\n // write generators\n for (const gen of presetZone.generators)\n {\n // name is deceptive, it works on negatives\n writeWord(pgendata, gen.generatorType);\n writeWord(pgendata, gen.generatorValue);\n }\n pgenIndex += presetZone.generators.length;\n }\n }\n // terminal generator, is zero\n writeWord(pgendata, 0);\n writeWord(pgendata, 0);\n \n return writeRIFFChunk(new RiffChunk(\n \"pgen\",\n pgendata.length,\n pgendata\n ));\n}", "import { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeLittleEndian, writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function getPMOD()\n{\n // very similar to imod,\n // go through all presets -> zones and write modulators sequentially\n let pmodsize = 10;\n for (const preset of this.presets)\n {\n pmodsize += preset.presetZones.reduce((sum, z) => z.modulators.length * 10 + sum, 0);\n }\n const pmoddata = new IndexedByteArray(pmodsize);\n let pmodIndex = 0;\n for (const preset of this.presets)\n {\n for (const pbag of preset.presetZones)\n {\n // set the start index here\n pbag.modulatorZoneStartIndex = pmodIndex;\n for (const mod of pbag.modulators)\n {\n writeWord(pmoddata, mod.sourceEnum);\n writeWord(pmoddata, mod.modulatorDestination);\n writeWord(pmoddata, mod.transformAmount);\n writeWord(pmoddata, mod.secondarySourceEnum);\n writeWord(pmoddata, mod.transformType);\n pmodIndex++;\n }\n }\n }\n \n // terminal modulator, is zero\n writeLittleEndian(pmoddata, 0, 10);\n \n return writeRIFFChunk(new RiffChunk(\n \"pmod\",\n pmoddata.length,\n pmoddata\n ));\n}", "import { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function getPBAG()\n{\n // write all pbag with their start indexes as they were changed in getPGEN() and getPMOD()\n const pbagsize = this.presets.reduce((sum, i) => i.presetZones.length * 4 + sum, 4);\n const pbagdata = new IndexedByteArray(pbagsize);\n let zoneID = 0;\n let generatorIndex = 0;\n let modulatorIndex = 0;\n for (const preset of this.presets)\n {\n preset.presetZoneStartIndex = zoneID;\n for (const pbag of preset.presetZones)\n {\n pbag.zoneID = zoneID;\n writeWord(pbagdata, generatorIndex);\n writeWord(pbagdata, modulatorIndex);\n generatorIndex += pbag.generators.length;\n modulatorIndex += pbag.modulators.length;\n zoneID++;\n }\n }\n // write the terminal PBAG\n writeWord(pbagdata, generatorIndex);\n writeWord(pbagdata, modulatorIndex);\n \n return writeRIFFChunk(new RiffChunk(\n \"pbag\",\n pbagdata.length,\n pbagdata\n ));\n}", "import { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeStringAsBytes } from \"../../../utils/byte_functions/string.js\";\nimport { writeDword, writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function getPHDR()\n{\n const phdrsize = this.presets.length * 38 + 38;\n const phdrdata = new IndexedByteArray(phdrsize);\n // the preset start is adjusted in pbag, this is only for the terminal preset index\n let presetStart = 0;\n for (const preset of this.presets)\n {\n writeStringAsBytes(phdrdata, preset.presetName, 20);\n writeWord(phdrdata, preset.program);\n writeWord(phdrdata, preset.bank);\n writeWord(phdrdata, presetStart);\n // 3 unused dword, spec says to keep em so we do\n writeDword(phdrdata, preset.library);\n writeDword(phdrdata, preset.genre);\n writeDword(phdrdata, preset.morphology);\n presetStart += preset.presetZones.length;\n }\n // write EOP\n writeStringAsBytes(phdrdata, \"EOP\", 20);\n writeWord(phdrdata, 0); // program\n writeWord(phdrdata, 0); // bank\n writeWord(phdrdata, presetStart);\n writeDword(phdrdata, 0); // library\n writeDword(phdrdata, 0); // genre\n writeDword(phdrdata, 0); // morphology\n \n return writeRIFFChunk(new RiffChunk(\n \"phdr\",\n phdrdata.length,\n phdrdata\n ));\n}", "import { combineArrays, IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { RiffChunk, writeRIFFChunk } from \"../riff_chunk.js\";\nimport { writeStringAsBytes } from \"../../../utils/byte_functions/string.js\";\nimport { consoleColors } from \"../../../utils/other.js\";\nimport { getIGEN } from \"./igen.js\";\nimport { getSDTA } from \"./sdta.js\";\nimport { getSHDR } from \"./shdr.js\";\nimport { getIMOD } from \"./imod.js\";\nimport { getIBAG } from \"./ibag.js\";\nimport { getINST } from \"./inst.js\";\nimport { getPGEN } from \"./pgen.js\";\nimport { getPMOD } from \"./pmod.js\";\nimport { getPBAG } from \"./pbag.js\";\nimport { getPHDR } from \"./phdr.js\";\nimport { writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../../../utils/loggin.js\";\n/**\n * @typedef {Object} SoundFont2WriteOptions\n * @property {boolean} compress - if the soundfont should be compressed with the Ogg Vorbis codec\n * @property {number} compressionQuality - the vorbis compression quality, from -0.1 to 1\n * @property {EncodeVorbisFunction|undefined} compressionFunction - the encode vorbis function.\n * Can be undefined if not compressed.\n */\n\n/**\n * @type {SoundFont2WriteOptions}\n */\nconst DEFAULT_WRITE_OPTIONS = {\n compress: false,\n compressionQuality: 0.5,\n compressionFunction: undefined\n};\n\n/**\n * Write the soundfont as an .sf2 file. This method is DESTRUCTIVE\n * @this {BasicSoundBank}\n * @param {SoundFont2WriteOptions} options\n * @returns {Uint8Array}\n */\nexport function write(options = DEFAULT_WRITE_OPTIONS)\n{\n if (options.compress)\n {\n if (typeof options.compressionFunction !== \"function\")\n {\n throw new TypeError(\"No compression function supplied but compression enabled.\");\n }\n }\n SpessaSynthGroupCollapsed(\n \"%cSaving soundfont...\",\n consoleColors.info\n );\n SpessaSynthInfo(\n `%cCompression: %c${options?.compress || \"false\"}%c quality: %c${options?.compressionQuality || \"none\"}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n SpessaSynthInfo(\n \"%cWriting INFO...\",\n consoleColors.info\n );\n /**\n * Write INFO\n * @type {IndexedByteArray[]}\n */\n const infoArrays = [];\n this.soundFontInfo[\"ISFT\"] = \"SpessaSynth\"; // ( \u0361\u00B0 \u035C\u0296 \u0361\u00B0)\n if (options?.compress)\n {\n this.soundFontInfo[\"ifil\"] = \"3.0\"; // set version to 3\n }\n \n for (const [type, data] of Object.entries(this.soundFontInfo))\n {\n if (type === \"ifil\" || type === \"iver\")\n {\n const major = parseInt(data.split(\".\")[0]);\n const minor = parseInt(data.split(\".\")[1]);\n const ckdata = new IndexedByteArray(4);\n writeWord(ckdata, major);\n writeWord(ckdata, minor);\n infoArrays.push(writeRIFFChunk(new RiffChunk(\n type,\n 4,\n ckdata\n )));\n }\n else if (type === \"DMOD\")\n {\n infoArrays.push(writeRIFFChunk(new RiffChunk(\n type,\n data.length,\n data\n )));\n }\n else\n {\n const arr = new IndexedByteArray(data.length);\n writeStringAsBytes(arr, data);\n infoArrays.push(writeRIFFChunk(new RiffChunk(\n type,\n data.length,\n arr\n )));\n }\n }\n const combined = combineArrays([\n new IndexedByteArray([73, 78, 70, 79]), // INFO\n ...infoArrays\n ]);\n const infoChunk = writeRIFFChunk(new RiffChunk(\"LIST\", combined.length, combined));\n \n SpessaSynthInfo(\n \"%cWriting SDTA...\",\n consoleColors.info\n );\n // write sdta\n const smplStartOffsets = [];\n const smplEndOffsets = [];\n const sdtaChunk = getSDTA.call(\n this,\n smplStartOffsets,\n smplEndOffsets,\n options?.compress,\n options?.compressionQuality ?? 0.5,\n options.compressionFunction\n );\n \n SpessaSynthInfo(\n \"%cWriting PDTA...\",\n consoleColors.info\n );\n // write pdta\n // go in reverse so the indexes are correct\n // instruments\n SpessaSynthInfo(\n \"%cWriting SHDR...\",\n consoleColors.info\n );\n const shdrChunk = getSHDR.call(this, smplStartOffsets, smplEndOffsets);\n SpessaSynthInfo(\n \"%cWriting IGEN...\",\n consoleColors.info\n );\n const igenChunk = getIGEN.call(this);\n SpessaSynthInfo(\n \"%cWriting IMOD...\",\n consoleColors.info\n );\n const imodChunk = getIMOD.call(this);\n SpessaSynthInfo(\n \"%cWriting IBAG...\",\n consoleColors.info\n );\n const ibagChunk = getIBAG.call(this);\n SpessaSynthInfo(\n \"%cWriting INST...\",\n consoleColors.info\n );\n const instChunk = getINST.call(this);\n // presets\n const pgenChunk = getPGEN.call(this);\n SpessaSynthInfo(\n \"%cWriting PMOD...\",\n consoleColors.info\n );\n const pmodChunk = getPMOD.call(this);\n SpessaSynthInfo(\n \"%cWriting PBAG...\",\n consoleColors.info\n );\n const pbagChunk = getPBAG.call(this);\n SpessaSynthInfo(\n \"%cWriting PHDR...\",\n consoleColors.info\n );\n const phdrChunk = getPHDR.call(this);\n // combine in the sfspec order\n const pdtadata = combineArrays([\n new IndexedByteArray([112, 100, 116, 97]), // \"pdta\"\n phdrChunk,\n pbagChunk,\n pmodChunk,\n pgenChunk,\n instChunk,\n ibagChunk,\n imodChunk,\n igenChunk,\n shdrChunk\n ]);\n const pdtaChunk = writeRIFFChunk(new RiffChunk(\n \"LIST\",\n pdtadata.length,\n pdtadata\n ));\n SpessaSynthInfo(\n \"%cWriting the output file...\",\n consoleColors.info\n );\n // finally, combine everything\n const riffdata = combineArrays([\n new IndexedByteArray([115, 102, 98, 107]), // \"sfbk\"\n infoChunk,\n sdtaChunk,\n pdtaChunk\n ]);\n \n const main = writeRIFFChunk(new RiffChunk(\n \"RIFF\",\n riffdata.length,\n riffdata\n ));\n SpessaSynthInfo(\n `%cSaved succesfully! Final file size: %c${main.length}`,\n consoleColors.info,\n consoleColors.recognized\n );\n SpessaSynthGroupEnd();\n return main;\n}", "/**\n * @typedef {Object} SoundFontRange\n * @property {number} min - the minimum midi note\n * @property {number} max - the maximum midi note\n */\n\nexport class BasicZone\n{\n /**\n * The zone's velocity range\n * min -1 means that it is a default value\n * @type {SoundFontRange}\n */\n velRange = { min: -1, max: 127 };\n \n /**\n * The zone's key range\n * min -1 means that it is a default value\n * @type {SoundFontRange}\n */\n keyRange = { min: -1, max: 127 };\n /**\n * Indicates if the zone is global\n * @type {boolean}\n */\n isGlobal = false;\n /**\n * The zone's generators\n * @type {Generator[]}\n */\n generators = [];\n /**\n * The zone's modulators\n * @type {Modulator[]}\n */\n modulators = [];\n \n /**\n * @returns {boolean}\n */\n get hasKeyRange()\n {\n return this.keyRange.min !== -1;\n }\n \n /**\n * @returns {boolean}\n */\n get hasVelRange()\n {\n return this.velRange.min !== -1;\n }\n \n /**\n * @param generatorType {generatorTypes}\n * @param notFoundValue {number}\n * @returns {number}\n */\n getGeneratorValue(generatorType, notFoundValue)\n {\n return this.generators.find(g => g.generatorType === generatorType)?.generatorValue ?? notFoundValue;\n }\n}\n\n", "import { BasicZone } from \"./basic_zone.js\";\n\nexport class BasicInstrumentZone extends BasicZone\n{\n /**\n * Zone's sample. Undefined if global\n * @type {BasicSample|undefined}\n */\n sample = undefined;\n /**\n * The zone's use count\n * @type {number}\n */\n useCount = 0;\n \n deleteZone()\n {\n this.useCount--;\n if (this.isGlobal)\n {\n return;\n }\n this.sample.useCount--;\n }\n}\n\nexport class BasicPresetZone extends BasicZone\n{\n /**\n * Zone's instrument. Undefined if global\n * @type {BasicInstrument|undefined}\n */\n instrument = undefined;\n \n deleteZone()\n {\n if (this.isGlobal)\n {\n return;\n }\n this.instrument.removeUseCount();\n }\n}", "import { Modulator } from \"../modulator.js\";\nimport { BasicInstrumentZone } from \"../basic_zones.js\";\nimport { Generator, generatorLimits, generatorTypes } from \"../generator.js\";\n\nconst notGlobalizedTypes = new Set([\n generatorTypes.velRange,\n generatorTypes.keyRange,\n generatorTypes.instrument,\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]);\n\n/**\n * Combines preset zones\n * @param preset {BasicPreset}\n * @param globalize {boolean}\n * @returns {BasicInstrumentZone[]}\n */\nexport function combineZones(preset, globalize = true)\n{\n /**\n * @param main {Generator[]}\n * @param adder {Generator[]}\n */\n function addUnique(main, adder)\n {\n main.push(...adder.filter(g => !main.find(mg => mg.generatorType === g.generatorType)));\n }\n \n /**\n * @param r1 {SoundFontRange}\n * @param r2 {SoundFontRange}\n * @returns {SoundFontRange}\n */\n function subtractRanges(r1, r2)\n {\n return { min: Math.max(r1.min, r2.min), max: Math.min(r1.max, r2.max) };\n }\n \n /**\n * @param main {Modulator[]}\n * @param adder {Modulator[]}\n */\n function addUniqueMods(main, adder)\n {\n main.push(...adder.filter(m => !main.find(mm => Modulator.isIdentical(m, mm))));\n }\n \n /**\n * @type {BasicInstrumentZone[]}\n */\n const finalZones = [];\n \n /**\n * @type {Generator[]}\n */\n const globalPresetGenerators = [];\n /**\n * @type {Modulator[]}\n */\n const globalPresetModulators = [];\n let globalPresetKeyRange = { min: 0, max: 127 };\n let globalPresetVelRange = { min: 0, max: 127 };\n \n // find the global zone and apply ranges, generators, and modulators\n const globalPresetZone = preset.presetZones.find(z => z.isGlobal);\n if (globalPresetZone)\n {\n globalPresetGenerators.push(...globalPresetZone.generators);\n globalPresetModulators.push(...globalPresetZone.modulators);\n globalPresetKeyRange = globalPresetZone.keyRange;\n globalPresetVelRange = globalPresetZone.velRange;\n }\n // for each non-global preset zone\n for (const presetZone of preset.presetZones)\n {\n if (presetZone.isGlobal)\n {\n continue;\n }\n // use global ranges if not provided\n let presetZoneKeyRange = presetZone.keyRange;\n if (!presetZone.hasKeyRange)\n {\n presetZoneKeyRange = globalPresetKeyRange;\n }\n let presetZoneVelRange = presetZone.velRange;\n if (!presetZone.hasVelRange)\n {\n presetZoneVelRange = globalPresetVelRange;\n }\n // add unique generators and modulators from the global zone\n const presetGenerators = presetZone.generators.map(g => new Generator(g.generatorType, g.generatorValue));\n addUnique(presetGenerators, globalPresetGenerators);\n const presetModulators = [...presetZone.modulators];\n addUniqueMods(presetModulators, globalPresetModulators);\n \n const iZones = presetZone.instrument.instrumentZones;\n /**\n * @type {Generator[]}\n */\n const globalInstGenerators = [];\n /**\n * @type {Modulator[]}\n */\n const globalInstModulators = [];\n let globalInstKeyRange = { min: 0, max: 127 };\n let globalInstVelRange = { min: 0, max: 127 };\n const globalInstZone = iZones.find(z => z.isGlobal);\n if (globalInstZone)\n {\n globalInstGenerators.push(...globalInstZone.generators);\n globalInstModulators.push(...globalInstZone.modulators);\n globalInstKeyRange = globalInstZone.keyRange;\n globalInstVelRange = globalInstZone.velRange;\n }\n // for each non-global instrument zone\n for (const instZone of iZones)\n {\n if (instZone.isGlobal)\n {\n continue;\n }\n // use global ranges if not provided\n let instZoneKeyRange = instZone.keyRange;\n if (!instZone.hasKeyRange)\n {\n instZoneKeyRange = globalInstKeyRange;\n }\n let instZoneVelRange = instZone.velRange;\n if (!instZone.hasVelRange)\n {\n instZoneVelRange = globalInstVelRange;\n }\n instZoneKeyRange = subtractRanges(instZoneKeyRange, presetZoneKeyRange);\n instZoneVelRange = subtractRanges(instZoneVelRange, presetZoneVelRange);\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 (instZoneKeyRange.max < instZoneKeyRange.min || 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(g => new Generator(g.generatorType, g.generatorValue));\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 * @type {Modulator[]}\n */\n const finalModList = [...instModulators];\n for (const mod of presetModulators)\n {\n const identicalInstMod = finalModList.findIndex(\n m => Modulator.isIdentical(mod, m));\n if (identicalInstMod !== -1)\n {\n // sum the amounts\n // (this makes a new modulator\n // because otherwise it would overwrite the one in the soundfont!\n finalModList[identicalInstMod] = finalModList[identicalInstMod].sumTransform(\n mod);\n }\n else\n {\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(g => new Generator(g.generatorType, g.generatorValue));\n for (const gen of presetGenerators)\n {\n if (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(g => g.generatorType === gen.generatorType);\n if (identicalInstGen !== -1)\n {\n // if exists, sum to that generator\n const newAmount = finalGenList[identicalInstGen].generatorValue + gen.generatorValue;\n finalGenList[identicalInstGen] = new Generator(gen.generatorType, newAmount);\n }\n else\n {\n // if not, sum to the default generator\n const newAmount = generatorLimits[gen.generatorType].def + gen.generatorValue;\n finalGenList.push(new Generator(gen.generatorType, newAmount));\n }\n }\n \n // remove unwanted\n finalGenList = finalGenList.filter(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 !== generatorLimits[g.generatorType].def\n );\n \n // create the zone and copy over values\n const zone = new BasicInstrumentZone();\n zone.keyRange = instZoneKeyRange;\n zone.velRange = instZoneVelRange;\n if (zone.keyRange.min === 0 && zone.keyRange.max === 127)\n {\n zone.keyRange.min = -1;\n }\n if (zone.velRange.min === 0 && zone.velRange.max === 127)\n {\n zone.velRange.min = -1;\n }\n zone.isGlobal = false;\n zone.sample = instZone.sample;\n zone.generators = finalGenList;\n zone.modulators = finalModList;\n finalZones.push(zone);\n }\n }\n \n if (globalize)\n {\n // create a global zone and add repeating generators to it\n // also modulators\n const globalZone = new BasicInstrumentZone();\n globalZone.isGlobal = true;\n // iterate over every type of generator\n for (let checkedType = 0; checkedType < 58; checkedType++)\n {\n // not these though\n if (notGlobalizedTypes.has(checkedType))\n {\n continue;\n }\n /**\n * @type {Object<string, number>}\n */\n let occurencesForValues = {};\n const defaultForChecked = generatorLimits[checkedType]?.def || 0;\n occurencesForValues[defaultForChecked] = 0;\n for (const z of finalZones)\n {\n const gen = z.generators.find(g => g.generatorType === checkedType);\n if (gen)\n {\n const value = gen.generatorValue;\n if (occurencesForValues[value] === undefined)\n {\n occurencesForValues[value] = 1;\n }\n else\n {\n occurencesForValues[value]++;\n }\n }\n else\n {\n occurencesForValues[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 {\n default:\n continue;\n \n case generatorTypes.decayVolEnv:\n relativeCounterpart = generatorTypes.keyNumToVolEnvDecay;\n break;\n case generatorTypes.holdVolEnv:\n relativeCounterpart = generatorTypes.keyNumToVolEnvHold;\n break;\n case generatorTypes.decayModEnv:\n relativeCounterpart = generatorTypes.keyNumToModEnvDecay;\n break;\n case generatorTypes.holdModEnv:\n relativeCounterpart = generatorTypes.keyNumToModEnvHold;\n }\n const relative = z.generators.find(g => g.generatorType === relativeCounterpart);\n if (relative !== undefined)\n {\n occurencesForValues = {};\n break;\n }\n }\n // if at least one occurrence, find the most used one and add it to global\n if (Object.keys(occurencesForValues).length > 0)\n {\n // [value, occurrences]\n const valueToGlobalize = Object.entries(occurencesForValues).reduce((max, curr) =>\n {\n if (max[1] < curr[1])\n {\n return curr;\n }\n return max;\n }, [0, 0]);\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 {\n globalZone.generators.push(new Generator(checkedType, targetValue));\n }\n // remove from the zones\n finalZones.forEach(z =>\n {\n const gen = z.generators.findIndex(g =>\n g.generatorType === checkedType);\n if (gen !== -1)\n {\n if (z.generators[gen].generatorValue === targetValue)\n {\n // That exact value exists. Since it's global now, remove it\n z.generators.splice(gen, 1);\n }\n }\n else\n {\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 {\n z.generators.push(new Generator(checkedType, defaultForChecked));\n }\n }\n });\n }\n }\n \n // globalize only modulators that exist in all zones\n const firstZone = finalZones.find(z => !z.isGlobal);\n const modulators = firstZone.modulators.map(m => Modulator.copy(m));\n for (const checkedModulator of modulators)\n {\n let existsForAllZones = true;\n for (const zone of finalZones)\n {\n if (zone.isGlobal || !existsForAllZones)\n {\n continue;\n }\n // check if that zone has an existing modulator\n const mod = zone.modulators.find(m => Modulator.isIdentical(m, checkedModulator));\n if (!mod)\n {\n // does not exist for this zone, so it's not global.\n existsForAllZones = false;\n }\n // exists.\n \n }\n if (existsForAllZones === true)\n {\n globalZone.modulators.push(Modulator.copy(checkedModulator));\n // delete it from local zones.\n for (const zone of finalZones)\n {\n const modulator = zone.modulators.find(m => Modulator.isIdentical(m, checkedModulator));\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 (modulator.transformAmount === checkedModulator.transformAmount)\n {\n zone.modulators.splice(zone.modulators.indexOf(modulator), 1);\n }\n }\n }\n }\n finalZones.splice(0, 0, globalZone);\n }\n return finalZones;\n}", "import { writeDword, writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeRIFFOddSize } from \"../riff_chunk.js\";\n\nconst WSMP_SIZE = 20;\n\n/**\n * @param sample {BasicSample}\n * @param rootKey {number}\n * @param tuning {number}\n * @param attenuationCentibels {number} CENTIBELS, NO CORRECTION\n * @param loopStart {number}\n * @param loopEnd {number}\n * @param loopingMode {number}\n * @returns {IndexedByteArray}\n */\nexport function writeWavesample(\n sample,\n rootKey,\n tuning,\n attenuationCentibels,\n loopStart,\n loopEnd,\n loopingMode)\n{\n let loopCount = loopingMode === 0 ? 0 : 1;\n const wsmpData = new IndexedByteArray(WSMP_SIZE + loopCount * 16);\n writeDword(wsmpData, WSMP_SIZE); // cbSize\n // usUnityNote (apply root pitch here)\n writeWord(wsmpData, rootKey);\n // sFineTune\n writeWord(wsmpData, tuning);\n \n // gain correction, use InitialAttenuation, apply attenuation correction\n const attenuationCb = attenuationCentibels * 0.4;\n \n // gain correction: Each unit of gain represents 1/655360 dB\n const lGain = Math.floor(attenuationCb * -65536);\n writeDword(wsmpData, lGain);\n // fulOptions: has to be 2, according to all DLS files I have\n writeDword(wsmpData, 2);\n \n const loopSize = loopEnd - loopStart;\n let ulLoopType = 0;\n switch (loopingMode)\n {\n default:\n case 0:\n // no loop\n loopCount = 0;\n break;\n \n case 1:\n // loop\n ulLoopType = 0;\n loopCount = 1;\n break;\n \n case 3:\n // loop and release\n ulLoopType = 1;\n loopCount = 1;\n }\n \n // cSampleLoops\n writeDword(wsmpData, loopCount);\n if (loopCount === 1)\n {\n writeDword(wsmpData, 16); // cbSize\n writeDword(wsmpData, ulLoopType);\n writeDword(wsmpData, loopStart);\n writeDword(wsmpData, loopSize);\n }\n return writeRIFFOddSize(\n \"wsmp\",\n wsmpData\n );\n}", "import { Modulator } from \"../basic_soundfont/modulator.js\";\nimport { generatorTypes } from \"../basic_soundfont/generator.js\";\n\n/**\n * @enum {number}\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};\n\nexport const DEFAULT_DLS_REVERB = new Modulator(\n 0x00DB,\n 0x0,\n generatorTypes.reverbEffectsSend,\n 1000,\n 0\n);\n\nexport const DEFAULT_DLS_CHORUS = new Modulator(\n 0x00DD,\n 0x0,\n generatorTypes.chorusEffectsSend,\n 1000,\n 0\n);\n\nexport const DLS_1_NO_VIBRATO_MOD = new Modulator(\n 0x0081,\n 0x0,\n generatorTypes.vibLfoToPitch,\n 0,\n 0\n);\n\nexport const DLS_1_NO_VIBRATO_PRESSURE = new Modulator(\n 0x000D,\n 0x0,\n generatorTypes.vibLfoToPitch,\n 0,\n 0\n);", "/**\n *\n * @enum {number}\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 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 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};", "import { IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeDword, writeWord } from \"../../../utils/byte_functions/little_endian.js\";\n\nexport class Articulator\n{\n /**\n * @type {DLSSources}\n */\n source;\n /**\n * @type {DLSSources}\n */\n control;\n /**\n * @type {DLSDestinations}\n */\n destination;\n /**\n * @type {number}\n */\n scale;\n /**\n * @type {number}\n */\n transform;\n \n constructor(source, control, destination, scale, transform)\n {\n this.source = source;\n this.control = control;\n this.destination = destination;\n this.scale = scale;\n this.transform = transform;\n }\n \n /**\n * @returns {IndexedByteArray}\n */\n writeArticulator()\n {\n const out = new IndexedByteArray(12);\n writeWord(out, this.source);\n writeWord(out, this.control);\n writeWord(out, this.destination);\n writeWord(out, this.transform);\n writeDword(out, this.scale << 16);\n return out;\n }\n}", "import { midiControllers } from \"../../../midi/midi_message.js\";\nimport { DLSSources } from \"../../dls/dls_sources.js\";\nimport { modulatorCurveTypes, modulatorSources } from \"../modulator.js\";\nimport { generatorTypes } from \"../generator.js\";\nimport { DLSDestinations } from \"../../dls/dls_destinations.js\";\nimport { Articulator } from \"./articulator.js\";\nimport { SpessaSynthWarn } from \"../../../utils/loggin.js\";\n\n\n/**\n * @param cc {boolean}\n * @param index {number}\n * @returns {number|undefined}\n */\nfunction getDLSSourceFromSf2Source(cc, index)\n{\n if (cc)\n {\n switch (index)\n {\n default:\n // DLS supports limited controllers\n return undefined;\n \n case midiControllers.modulationWheel:\n return DLSSources.modulationWheel;\n case midiControllers.mainVolume:\n return DLSSources.volume;\n case midiControllers.pan:\n return DLSSources.pan;\n case midiControllers.expressionController:\n return DLSSources.expression;\n case midiControllers.chorusDepth:\n return DLSSources.chorus;\n case midiControllers.reverbDepth:\n return DLSSources.reverb;\n }\n }\n else\n {\n switch (index)\n {\n default:\n // cannot be a DLS articulator\n return undefined;\n \n case modulatorSources.noteOnKeyNum:\n return DLSSources.keyNum;\n case modulatorSources.noteOnVelocity:\n return DLSSources.velocity;\n case modulatorSources.noController:\n return DLSSources.none;\n case modulatorSources.polyPressure:\n return DLSSources.polyPressure;\n case modulatorSources.channelPressure:\n return DLSSources.channelPressure;\n case modulatorSources.pitchWheel:\n return DLSSources.pitchWheel;\n case modulatorSources.pitchWheelRange:\n return DLSSources.pitchWheelRange;\n }\n }\n}\n\n/**\n * @param dest {number}\n * @param amount {number}\n * @returns {number|undefined|{dest: number, amount: number}}\n */\nfunction getDLSDestinationFromSf2(dest, amount)\n{\n switch (dest)\n {\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 { dest: DLSDestinations.gain, amount: -amount };\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 { dest: DLSDestinations.volEnvSustain, amount: 1000 - amount };\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 { dest: DLSDestinations.modEnvSustain, amount: 1000 - amount };\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}\n\n/**\n * @param dest {number}\n * @param amt {number}\n * @returns {{source: DLSSources, dest: DLSDestinations, amt: number, isBipolar: boolean}|undefined}\n */\nfunction checkSF2SpecialCombos(dest, amt)\n{\n \n switch (dest)\n {\n default:\n return undefined;\n // mod env\n case generatorTypes.modEnvToFilterFc:\n return { source: DLSSources.modEnv, dest: DLSDestinations.filterCutoff, amt: amt, isBipolar: false };\n case generatorTypes.modEnvToPitch:\n return { source: DLSSources.modEnv, dest: DLSDestinations.pitch, amt: amt, isBipolar: false };\n \n // mod lfo\n case generatorTypes.modLfoToFilterFc:\n return { source: DLSSources.modLfo, dest: DLSDestinations.filterCutoff, amt: amt, isBipolar: true };\n case generatorTypes.modLfoToVolume:\n return { source: DLSSources.modLfo, dest: DLSDestinations.gain, amt: amt, isBipolar: true };\n case generatorTypes.modLfoToPitch:\n return { source: DLSSources.modLfo, dest: DLSDestinations.pitch, amt: amt, isBipolar: true };\n \n // vib lfo\n case generatorTypes.vibLfoToPitch:\n return { source: DLSSources.vibratoLfo, dest: DLSDestinations.pitch, amt: amt, isBipolar: true };\n \n // key to something\n case generatorTypes.keyNumToVolEnvHold:\n return {\n source: DLSSources.keyNum,\n dest: DLSDestinations.volEnvHold,\n amt: amt,\n isBipolar: true\n };\n case generatorTypes.keyNumToVolEnvDecay:\n return {\n source: DLSSources.keyNum,\n dest: DLSDestinations.volEnvDecay,\n amt: amt,\n isBipolar: true\n };\n case generatorTypes.keyNumToModEnvHold:\n return {\n source: DLSSources.keyNum,\n dest: DLSDestinations.modEnvHold,\n amt: amt,\n isBipolar: true\n };\n case generatorTypes.keyNumToModEnvDecay:\n return {\n source: DLSSources.keyNum,\n dest: DLSDestinations.modEnvDecay,\n amt: amt,\n isBipolar: true\n };\n \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 case generatorTypes.scaleTuning:\n return {\n source: DLSSources.keyNum,\n dest: DLSDestinations.pitch,\n amt: amt * 128,\n isBipolar: false // according to table 4, this should be false.\n };\n }\n}\n\n/**\n * @param gen {Generator}\n * @returns {Articulator|undefined}\n */\nexport function getDLSArticulatorFromSf2Generator(gen)\n{\n const dest = getDLSDestinationFromSf2(gen.generatorType, gen.generatorValue);\n let destination = dest;\n let source = 0;\n let amount = gen.generatorValue;\n if (dest?.amount !== undefined)\n {\n amount = dest.amount;\n destination = dest.dest;\n }\n // check for special combo\n const combo = checkSF2SpecialCombos(gen.generatorType, gen.generatorValue);\n if (combo !== undefined)\n {\n amount = combo.amt;\n destination = combo.dest;\n source = combo.source;\n }\n else if (destination === undefined)\n {\n SpessaSynthWarn(`Invalid generator type: ${gen.generatorType}`);\n return undefined;\n }\n return new Articulator(\n source,\n 0,\n destination,\n amount,\n 0\n );\n}\n\n\n/**\n * @param mod {Modulator}\n * @returns {Articulator|undefined}\n */\nexport function getDLSArticulatorFromSf2Modulator(mod)\n{\n if (mod.transformType !== 0)\n {\n SpessaSynthWarn(\"Other transform types are not supported.\");\n return undefined;\n }\n let source = getDLSSourceFromSf2Source(mod.sourceUsesCC, mod.sourceIndex);\n let sourceTransformType = mod.sourceCurveType;\n let sourceBipolar = mod.sourcePolarity;\n let sourceDirection = mod.sourceDirection;\n if (source === undefined)\n {\n SpessaSynthWarn(`Invalid source: ${mod.sourceIndex}, CC: ${mod.sourceUsesCC}`);\n return undefined;\n }\n // Attenuation is the opposite of gain. Invert.\n if (mod.modulatorDestination === generatorTypes.initialAttenuation)\n {\n sourceDirection = sourceDirection === 1 ? 0 : 1;\n }\n let control = getDLSSourceFromSf2Source(mod.secSrcUsesCC, mod.secSrcIndex);\n let controlTransformType = mod.secSrcCurveType;\n let controlBipolar = mod.secSrcPolarity;\n let controlDirection = mod.secSrcDirection;\n if (control === undefined)\n {\n SpessaSynthWarn(`Invalid secondary source: ${mod.secSrcIndex}, CC: ${mod.secSrcUsesCC}`);\n return undefined;\n }\n let dlsDestinationFromSf2 = getDLSDestinationFromSf2(mod.modulatorDestination, mod.transformAmount);\n let destination = dlsDestinationFromSf2;\n let amt = mod.transformAmount;\n if (dlsDestinationFromSf2?.dest !== undefined)\n {\n destination = dlsDestinationFromSf2.dest;\n amt = dlsDestinationFromSf2.amount;\n }\n const specialCombo = checkSF2SpecialCombos(mod.modulatorDestination, mod.transformAmount);\n if (specialCombo !== undefined)\n {\n amt = specialCombo.amt;\n // move the source to control\n control = source;\n controlTransformType = sourceTransformType;\n controlBipolar = sourceBipolar;\n controlDirection = sourceDirection;\n \n // set source as static as it's either: env, lfo or key num\n sourceTransformType = modulatorCurveTypes.linear;\n sourceBipolar = specialCombo.isBipolar ? 1 : 0;\n sourceDirection = 0;\n source = specialCombo.source;\n destination = specialCombo.dest;\n }\n else if (destination === undefined)\n {\n SpessaSynthWarn(`Invalid destination: ${mod.modulatorDestination}`);\n return undefined;\n }\n \n // source curve type maps to a desfont curve type in section 2.10, table 9\n let transform = 0;\n transform |= controlTransformType << 4;\n transform |= controlBipolar << 8;\n transform |= controlDirection << 9;\n \n // use the source curve in output transform\n transform |= sourceTransformType;\n transform |= sourceBipolar << 14;\n transform |= sourceDirection << 15;\n return new Articulator(\n source,\n control,\n destination,\n amt,\n transform\n );\n}", "import { getDLSArticulatorFromSf2Generator, getDLSArticulatorFromSf2Modulator } from \"./modulator_converter.js\";\nimport { writeRIFFOddSize } from \"../riff_chunk.js\";\nimport { combineArrays, IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { Generator, generatorTypes } from \"../generator.js\";\nimport { writeDword } from \"../../../utils/byte_functions/little_endian.js\";\nimport { consoleColors } from \"../../../utils/other.js\";\nimport { SpessaSynthInfo, SpessaSynthWarn } from \"../../../utils/loggin.js\";\nimport { Modulator } from \"../modulator.js\";\nimport {\n DEFAULT_DLS_CHORUS,\n DEFAULT_DLS_REVERB,\n DLS_1_NO_VIBRATO_MOD,\n DLS_1_NO_VIBRATO_PRESSURE\n} from \"../../dls/dls_sources.js\";\n\nconst invalidGeneratorTypes = new Set([\n generatorTypes.sampleModes,\n generatorTypes.initialAttenuation,\n generatorTypes.keyRange,\n generatorTypes.velRange,\n generatorTypes.sampleID,\n generatorTypes.fineTune,\n generatorTypes.coarseTune,\n generatorTypes.startAddrsOffset,\n generatorTypes.startAddrsCoarseOffset,\n generatorTypes.endAddrOffset,\n generatorTypes.endAddrsCoarseOffset,\n generatorTypes.startloopAddrsOffset,\n generatorTypes.startloopAddrsCoarseOffset,\n generatorTypes.endloopAddrsOffset,\n generatorTypes.endloopAddrsCoarseOffset,\n generatorTypes.overridingRootKey,\n generatorTypes.exclusiveClass\n]);\n\n/**\n * @param zone {BasicInstrumentZone}\n * @returns {IndexedByteArray}\n */\nexport function writeArticulator(zone)\n{\n \n \n // envelope generators are limited to 40 seconds\n // in timecents, this is 1200 * log2(10) = 6386\n \n for (let i = 0; i < zone.generators.length; i++)\n {\n const g = zone.generators[i];\n if (\n g.generatorType === generatorTypes.delayVolEnv ||\n g.generatorType === generatorTypes.attackVolEnv ||\n g.generatorType === generatorTypes.holdVolEnv ||\n g.generatorType === generatorTypes.decayVolEnv ||\n g.generatorType === generatorTypes.releaseVolEnv ||\n g.generatorType === generatorTypes.delayModEnv ||\n g.generatorType === generatorTypes.attackModEnv ||\n g.generatorType === generatorTypes.holdModEnv ||\n g.generatorType === generatorTypes.decayModEnv\n )\n {\n zone.generators[i] = new Generator(g.generatorType, Math.min(g.generatorValue, 6386), false);\n }\n }\n \n \n // read_articulation.js:\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 invert this here\n for (let i = 0; i < zone.generators.length; i++)\n {\n const relativeGenerator = zone.generators[i];\n let absoluteCounterpart = undefined;\n switch (relativeGenerator.generatorType)\n {\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 let absoluteGenerator = zone.generators.find(g => g.generatorType === absoluteCounterpart);\n if (absoluteGenerator === undefined)\n {\n // there's no absolute generator here.\n continue;\n }\n const dlsRelative = relativeGenerator.generatorValue * -128;\n const subtraction = (60 / 128) * dlsRelative;\n const newAbsolute = absoluteGenerator.generatorValue - subtraction;\n \n const iR = zone.generators.indexOf(relativeGenerator);\n const iA = zone.generators.indexOf(absoluteGenerator);\n zone.generators[iA] =\n new Generator(absoluteCounterpart, newAbsolute, false);\n zone.generators[iR] =\n new Generator(relativeGenerator.generatorType, dlsRelative, false);\n }\n /**\n * @type {Articulator[]}\n */\n const generators = zone.generators.reduce((arrs, g) =>\n {\n if (invalidGeneratorTypes.has(g.generatorType))\n {\n return arrs;\n }\n const art = getDLSArticulatorFromSf2Generator(g);\n if (art !== undefined)\n {\n arrs.push(art);\n SpessaSynthInfo(\"%cSucceeded converting to DLS Articulator!\", consoleColors.recognized);\n \n }\n else\n {\n SpessaSynthWarn(\"Failed converting to DLS Articulator!\");\n }\n return arrs;\n }, []);\n /**\n * @type {Articulator[]}\n */\n const modulators = zone.modulators.reduce((arrs, m) =>\n {\n // do not write the default DLS modulators\n if (\n Modulator.isIdentical(m, DEFAULT_DLS_CHORUS, true) ||\n Modulator.isIdentical(m, DEFAULT_DLS_REVERB, true) ||\n Modulator.isIdentical(m, DLS_1_NO_VIBRATO_MOD, true) ||\n Modulator.isIdentical(m, DLS_1_NO_VIBRATO_PRESSURE, true)\n )\n {\n return arrs;\n }\n const art = getDLSArticulatorFromSf2Modulator(m);\n if (art !== undefined)\n {\n arrs.push(art);\n SpessaSynthInfo(\"%cSucceeded converting to DLS Articulator!\", consoleColors.recognized);\n \n }\n else\n {\n SpessaSynthWarn(\"Failed converting to DLS Articulator!\");\n }\n return arrs;\n }, []);\n generators.push(...modulators);\n \n const art2Data = new IndexedByteArray(8);\n writeDword(art2Data, 8); // cbSize\n writeDword(art2Data, generators.length); // cbConnectionBlocks\n \n \n const out = generators.map(a => a.writeArticulator());\n return writeRIFFOddSize(\n \"art2\",\n combineArrays([art2Data, ...out])\n );\n}", "import { combineArrays, IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeDword, writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { generatorTypes } from \"../generator.js\";\nimport { writeRIFFOddSize } from \"../riff_chunk.js\";\nimport { writeWavesample } from \"./wsmp.js\";\nimport { writeArticulator } from \"./art2.js\";\n\n/**\n * @param zone {BasicInstrumentZone}\n * @param globalZone {BasicInstrumentZone}\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function writeDLSRegion(zone, globalZone)\n{\n // region header\n const rgnhData = new IndexedByteArray(12);\n // keyRange\n writeWord(rgnhData, Math.max(zone.keyRange.min, 0));\n writeWord(rgnhData, zone.keyRange.max);\n // velRange\n writeWord(rgnhData, Math.max(zone.velRange.min, 0));\n writeWord(rgnhData, zone.velRange.max);\n // fusOptions: 0 it seems\n writeWord(rgnhData, 0);\n // keyGroup (exclusive class)\n const exclusive = zone.getGeneratorValue(generatorTypes.exclusiveClass, 0);\n writeWord(rgnhData, exclusive);\n // usLayer\n writeWord(rgnhData, 0);\n const rgnh = writeRIFFOddSize(\n \"rgnh\",\n rgnhData\n );\n \n let rootKey = zone.getGeneratorValue(generatorTypes.overridingRootKey, zone.sample.samplePitch);\n \n // a lot of soundfonts 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 const scaleTuning = zone.getGeneratorValue(\n generatorTypes.scaleTuning,\n globalZone.getGeneratorValue(generatorTypes.scaleTuning, 100)\n );\n if (scaleTuning === 0 && zone.keyRange.max - zone.keyRange.min === 0)\n {\n rootKey = zone.keyRange.min;\n }\n \n // wave sample (Wsmp)\n const wsmp = writeWavesample(\n zone.sample,\n rootKey,\n zone.getGeneratorValue(\n generatorTypes.fineTune,\n 0\n ) + zone.getGeneratorValue(generatorTypes.coarseTune, 0) * 100\n + zone.sample.samplePitchCorrection,\n zone.getGeneratorValue(generatorTypes.initialAttenuation, 0),\n // calculate loop with offsets\n zone.sample.sampleLoopStartIndex\n + zone.getGeneratorValue(generatorTypes.startloopAddrsOffset, 0)\n + zone.getGeneratorValue(generatorTypes.startloopAddrsCoarseOffset, 0) * 32768,\n zone.sample.sampleLoopEndIndex\n + zone.getGeneratorValue(generatorTypes.endloopAddrsOffset, 0)\n + zone.getGeneratorValue(generatorTypes.endloopAddrsCoarseOffset, 0) * 32768,\n zone.getGeneratorValue(generatorTypes.sampleModes, 0)\n );\n \n // wave link (wlnk)\n const wlnkData = new IndexedByteArray(12);\n writeWord(wlnkData, 0); // fusOptions\n writeWord(wlnkData, 0); // usPhaseGroup\n // let sampleType = 0;\n // switch (zone.sample.sampleType)\n // {\n // default:\n // case 1:\n // case 4:\n // // mono/left\n // sampleType = 0;\n // break;\n //\n // case 2:\n // // right\n // sampleType = 1;\n // }\n // 1 means that the first bit is on so mono/left\n writeDword(wlnkData, 1); // ulChannel\n writeDword(wlnkData, this.samples.indexOf(zone.sample)); // ulTableIndex\n const wlnk = writeRIFFOddSize(\n \"wlnk\",\n wlnkData\n );\n \n // art\n let lar2 = new IndexedByteArray(0);\n if (zone.modulators.length + zone.generators.length > 0)\n {\n const art2 = writeArticulator(zone);\n \n lar2 = writeRIFFOddSize(\n \"lar2\",\n art2,\n false,\n true\n );\n }\n \n return writeRIFFOddSize(\n \"rgn2\",\n combineArrays([\n rgnh,\n wsmp,\n wlnk,\n lar2\n ]),\n false,\n true\n );\n}", "import { combineArrays, IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { combineZones } from \"./combine_zones.js\";\nimport { writeRIFFOddSize } from \"../riff_chunk.js\";\nimport { writeDword } from \"../../../utils/byte_functions/little_endian.js\";\nimport { writeDLSRegion } from \"./rgn2.js\";\nimport { getStringBytesZero } from \"../../../utils/byte_functions/string.js\";\nimport { writeArticulator } from \"./art2.js\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from \"../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../utils/other.js\";\n\n/**\n * @this {BasicSoundBank}\n * @param preset {BasicPreset}\n * @returns {IndexedByteArray}\n */\nexport function writeIns(preset)\n{\n SpessaSynthGroupCollapsed(\n `%cWriting %c${preset.presetName}%c...`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n // combine preset and instrument zones into a single instrument zone (region) list\n const combined = combineZones(preset);\n \n const nonGlobalRegionsCount = combined.reduce((sum, z) =>\n {\n if (!z.isGlobal)\n {\n return sum + 1;\n }\n return sum;\n }, 0);\n \n // insh: instrument header\n const inshData = new IndexedByteArray(12);\n writeDword(inshData, nonGlobalRegionsCount); // cRegions\n // bank MSB is in bits 8-14\n let ulBank = (preset.bank & 127) << 8;\n // bit 32 means drums\n if (preset.bank === 128)\n {\n ulBank |= (1 << 31);\n }\n writeDword(inshData, ulBank); // ulBank\n writeDword(inshData, preset.program & 127); // ulInstrument\n \n const insh = writeRIFFOddSize(\n \"insh\",\n inshData\n );\n \n // write global zone\n let lar2 = new IndexedByteArray(0);\n const globalZone = combined.find(z => z.isGlobal === true);\n if (globalZone)\n {\n const art2 = writeArticulator(globalZone);\n lar2 = writeRIFFOddSize(\n \"lar2\",\n art2,\n false,\n true\n );\n }\n \n // write the region list\n const lrgnData = combineArrays(combined.reduce((arrs, z) =>\n {\n if (!z.isGlobal)\n {\n arrs.push(writeDLSRegion.apply(this, [z, globalZone]));\n }\n return arrs;\n }, []));\n const lrgn = writeRIFFOddSize(\n \"lrgn\",\n lrgnData,\n false,\n true\n );\n \n // writeINFO\n const inam = writeRIFFOddSize(\n \"INAM\",\n getStringBytesZero(preset.presetName)\n );\n const info = writeRIFFOddSize(\n \"INFO\",\n inam,\n false,\n true\n );\n \n SpessaSynthGroupEnd();\n return writeRIFFOddSize(\n \"ins \",\n combineArrays([insh, lrgn, lar2, info]),\n false,\n true\n );\n}", "import { writeRIFFOddSize } from \"../riff_chunk.js\";\nimport { combineArrays } from \"../../../utils/indexed_array.js\";\nimport { writeIns } from \"./ins.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {IndexedByteArray}\n */\nexport function writeLins()\n{\n const lins = combineArrays(this.presets.map(p => writeIns.apply(this, [p])));\n return writeRIFFOddSize(\n \"lins\",\n lins,\n false,\n true\n );\n}", "import { combineArrays, IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeDword, writeWord } from \"../../../utils/byte_functions/little_endian.js\";\nimport { writeRIFFOddSize } from \"../riff_chunk.js\";\nimport { writeWavesample } from \"./wsmp.js\";\nimport { getStringBytesZero } from \"../../../utils/byte_functions/string.js\";\nimport { SpessaSynthInfo } from \"../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../utils/other.js\";\n\n/**\n * @param sample {BasicSample}\n * @returns {IndexedByteArray}\n */\nexport function writeDLSSample(sample)\n{\n const fmtData = new IndexedByteArray(18);\n writeWord(fmtData, 1); // wFormatTag\n writeWord(fmtData, 1); // wChannels\n writeDword(fmtData, sample.sampleRate);\n writeDword(fmtData, sample.sampleRate * 2); // 16-bit samples\n writeWord(fmtData, 2); // wBlockAlign\n writeWord(fmtData, 16); // wBitsPerSample\n const fmt = writeRIFFOddSize(\n \"fmt \",\n fmtData\n );\n let loop = 1;\n if (sample.sampleLoopStartIndex + Math.abs(sample.getAudioData().length - sample.sampleLoopEndIndex) < 2)\n {\n loop = 0;\n }\n const wsmp = writeWavesample(\n sample,\n sample.samplePitch,\n sample.samplePitchCorrection,\n 0,\n sample.sampleLoopStartIndex,\n sample.sampleLoopEndIndex,\n loop\n );\n const audio = sample.getAudioData();\n let data;\n // if sample is compressed, getRawData cannot be used\n if (sample.isCompressed)\n {\n const data16 = new Int16Array(audio.length);\n \n for (let i = 0; i < audio.length; i++)\n {\n // 32,767, as 32,768 may cause overflow (because vorbis can go above 1 sometimes)\n data16[i] = audio[i] * 32767;\n }\n \n \n data = writeRIFFOddSize(\n \"data\",\n new IndexedByteArray(data16.buffer)\n );\n }\n else\n {\n data = writeRIFFOddSize(\n \"data\",\n sample.getRawData()\n );\n }\n \n const inam = writeRIFFOddSize(\n \"INAM\",\n getStringBytesZero(sample.sampleName)\n );\n const info = writeRIFFOddSize(\n \"INFO\",\n inam,\n false,\n true\n );\n SpessaSynthInfo(\n `%cSaved %c${sample.sampleName}%c succesfully!`,\n consoleColors.recognized,\n consoleColors.value,\n consoleColors.recognized\n );\n return writeRIFFOddSize(\n \"wave\",\n combineArrays([\n fmt,\n wsmp,\n data,\n info\n ]),\n false,\n true\n );\n}", "import { writeDLSSample } from \"./wave.js\";\nimport { writeRIFFOddSize } from \"../riff_chunk.js\";\nimport { combineArrays } from \"../../../utils/indexed_array.js\";\n\n/**\n * @this {BasicSoundBank}\n * @returns {{data: IndexedByteArray, indexes: number[] }}\n */\nexport function writeWavePool()\n{\n let currentIndex = 0;\n const offsets = [];\n /**\n * @type {IndexedByteArray[]}\n */\n const samples = this.samples.map(s =>\n {\n const out = writeDLSSample(s);\n offsets.push(currentIndex);\n currentIndex += out.length;\n return out;\n });\n return {\n data: writeRIFFOddSize(\n \"wvpl\",\n combineArrays(samples),\n false,\n true\n ),\n indexes: offsets\n };\n}", "import { writeRIFFOddSize } from \"../riff_chunk.js\";\nimport { writeDword } from \"../../../utils/byte_functions/little_endian.js\";\nimport { combineArrays, IndexedByteArray } from \"../../../utils/indexed_array.js\";\nimport { writeLins } from \"./lins.js\";\nimport { getStringBytesZero, writeStringAsBytes } from \"../../../utils/byte_functions/string.js\";\nimport { writeWavePool } from \"./wvpl.js\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../utils/other.js\";\n\n/**\n * Write the soundfont as a .dls file. Experimental\n * @this {BasicSoundBank}\n * @returns {Uint8Array}\n */\nexport function writeDLS()\n{\n SpessaSynthGroupCollapsed(\n \"%cSaving DLS...\",\n consoleColors.info\n );\n // write colh\n const colhNum = new IndexedByteArray(4);\n writeDword(colhNum, this.presets.length);\n const colh = writeRIFFOddSize(\n \"colh\",\n colhNum\n );\n SpessaSynthGroupCollapsed(\n \"%cWriting instruments...\",\n consoleColors.info\n );\n const lins = writeLins.apply(this);\n SpessaSynthInfo(\n \"%cSuccess!\",\n consoleColors.recognized\n );\n SpessaSynthGroupEnd();\n \n SpessaSynthGroupCollapsed(\n \"%cWriting WAVE samples...\",\n consoleColors.info\n );\n const wavepool = writeWavePool.apply(this);\n const wvpl = wavepool.data;\n const ptblOffsets = wavepool.indexes;\n SpessaSynthInfo(\"%cSucceeded!\", consoleColors.recognized);\n SpessaSynthGroupEnd();\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 {\n writeDword(ptblData, offset);\n }\n const ptbl = writeRIFFOddSize(\n \"ptbl\",\n ptblData\n );\n \n this.soundFontInfo[\"ICMT\"] = (this.soundFontInfo[\"ICMT\"] || \"Soundfont\") + \"\\nConverted from SF2 to DLS using SpessaSynth\";\n this.soundFontInfo[\"ISFT\"] = \"SpessaSynth\";\n // write INFO\n const infos = [];\n for (const [info, data] of Object.entries(this.soundFontInfo))\n {\n if (\n info !== \"ICMT\" &&\n info !== \"INAM\" &&\n info !== \"ICRD\" &&\n info !== \"IENG\" &&\n info !== \"ICOP\" &&\n info !== \"ISFT\" &&\n info !== \"ISBJ\"\n )\n {\n continue;\n }\n infos.push(\n writeRIFFOddSize(\n info,\n getStringBytesZero(data),\n true\n )\n );\n }\n const info = writeRIFFOddSize(\n \"INFO\",\n combineArrays(infos),\n false,\n true\n );\n \n const out = new IndexedByteArray(\n colh.length\n + lins.length\n + ptbl.length\n + wvpl.length\n + info.length\n + 4);\n writeStringAsBytes(out, \"DLS \");\n out.set(combineArrays([\n colh,\n lins,\n ptbl,\n wvpl,\n info\n ]), 4);\n SpessaSynthInfo(\n \"%cSaved succesfully!\",\n consoleColors.recognized\n );\n SpessaSynthGroupEnd();\n return writeRIFFOddSize(\n \"RIFF\",\n out\n );\n}", "/**\n * samples.js\n * purpose: parses soundfont samples, resamples if needed.\n * loads sample data, handles async loading of sf3 compressed samples\n */\nimport { SpessaSynthWarn } from \"../../utils/loggin.js\";\n\n// should be reasonable for most cases\nconst RESAMPLE_RATE = 48000;\n\n/**\n * @typedef {function} EncodeVorbisFunction\n * @param channelAudioData {Float32Array[]}\n * @param sampleRate {number}\n * @param channels {number}\n * @param quality {number} -0.1 to 1\n * @returns {Uint8Array}\n */\n\nexport class BasicSample\n{\n \n /**\n * The sample's name\n * @type {string}\n */\n sampleName;\n \n /**\n * Sample rate in Hz\n * @type {number}\n */\n sampleRate;\n \n /**\n * Original pitch of the sample as a MIDI note number\n * @type {number}\n */\n samplePitch;\n \n /**\n * Pitch correction, in cents. Can be negative\n * @type {number}\n */\n samplePitchCorrection;\n \n /**\n * Sample link, currently unused here\n * @type {number}\n */\n sampleLink;\n \n /**\n * Type of the sample, currently only used for SF3\n * @type {number}\n */\n sampleType;\n \n /**\n * Relative to the start of the sample in sample points\n * @type {number}\n */\n sampleLoopStartIndex;\n \n /**\n * Relative to the start of the sample in sample points\n * @type {number}\n */\n sampleLoopEndIndex;\n \n /**\n * Indicates if the sample is compressed\n * @type {boolean}\n */\n isCompressed;\n \n /**\n * The compressed sample data if it was compressed by spessasynth\n * @type {Uint8Array}\n */\n compressedData = undefined;\n \n /**\n * The sample's use count\n * @type {number}\n */\n useCount = 0;\n \n /**\n * The sample's audio data\n * @type {Float32Array}\n */\n sampleData = undefined;\n \n /**\n * The basic representation of a soundfont sample\n * @param sampleName {string} The sample's name\n * @param sampleRate {number} The sample's rate in Hz\n * @param samplePitch {number} The sample's pitch as a MIDI note number\n * @param samplePitchCorrection {number} The sample's pitch correction in cents\n * @param sampleLink {number} The sample's link, currently unused\n * @param sampleType {number} The sample's type, an enum\n * @param loopStart {number} The sample's loop start relative to the sample start in sample points\n * @param loopEnd {number} The sample's loop end relative to the sample start in sample points\n */\n constructor(\n sampleName,\n sampleRate,\n samplePitch,\n samplePitchCorrection,\n sampleLink,\n sampleType,\n loopStart,\n loopEnd\n )\n {\n this.sampleName = sampleName;\n this.sampleRate = sampleRate;\n this.samplePitch = samplePitch;\n this.samplePitchCorrection = samplePitchCorrection;\n this.sampleLink = sampleLink;\n this.sampleType = sampleType;\n this.sampleLoopStartIndex = loopStart;\n this.sampleLoopEndIndex = loopEnd;\n // https://github.com/FluidSynth/fluidsynth/wiki/SoundFont3Format\n this.isCompressed = (sampleType & 0x10) > 0;\n }\n \n \n /**\n * @returns {Uint8Array|IndexedByteArray}\n */\n getRawData()\n {\n const uint8 = new Uint8Array(this.sampleData.length * 2);\n for (let i = 0; i < this.sampleData.length; i++)\n {\n const sample = Math.floor(this.sampleData[i] * 32768);\n uint8[i * 2] = sample & 0xFF; // lower byte\n uint8[i * 2 + 1] = (sample >> 8) & 0xFF; // upper byte\n }\n return uint8;\n }\n \n resampleData(newSampleRate)\n {\n let audioData = this.getAudioData();\n const ratio = newSampleRate / this.sampleRate;\n const resampled = new Float32Array(Math.floor(audioData.length * ratio));\n for (let i = 0; i < resampled.length; i++)\n {\n resampled[i] = audioData[Math.floor(i * (1 / ratio))];\n }\n audioData = resampled;\n this.sampleRate = newSampleRate;\n // adjust loop points\n this.sampleLoopStartIndex = Math.floor(this.sampleLoopStartIndex * ratio);\n this.sampleLoopEndIndex = Math.floor(this.sampleLoopEndIndex * ratio);\n this.sampleData = audioData;\n }\n \n /**\n * @param quality {number}\n * @param encodeVorbis {EncodeVorbisFunction}\n */\n compressSample(quality, encodeVorbis)\n {\n // no need to compress\n if (this.isCompressed)\n {\n return;\n }\n // compress, always mono!\n try\n {\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 {\n this.resampleData(RESAMPLE_RATE);\n audioData = this.getAudioData();\n }\n this.compressedData = encodeVorbis([audioData], 1, this.sampleRate, quality);\n // flag as compressed\n this.sampleType |= 0x10;\n this.isCompressed = true;\n }\n catch (e)\n {\n SpessaSynthWarn(`Failed to compress ${this.sampleName}. Leaving as uncompressed!`);\n this.isCompressed = false;\n this.compressedData = undefined;\n // flag as uncompressed\n this.sampleType &= 0xEF;\n }\n \n }\n \n /**\n * @returns {Float32Array}\n */\n getAudioData()\n {\n return this.sampleData;\n }\n}", "export class BasicInstrument\n{\n /**\n * The instrument's name\n * @type {string}\n */\n instrumentName = \"\";\n \n /**\n * The instrument's zones\n * @type {BasicInstrumentZone[]}\n */\n instrumentZones = [];\n \n /**\n * Instrument's use count, used for trimming\n * @type {number}\n * @private\n */\n _useCount = 0;\n \n /**\n * @returns {number}\n */\n get useCount()\n {\n return this._useCount;\n }\n \n addUseCount()\n {\n this._useCount++;\n this.instrumentZones.forEach(z => z.useCount++);\n }\n \n removeUseCount()\n {\n this._useCount--;\n for (let i = 0; i < this.instrumentZones.length; i++)\n {\n if (this.safeDeleteZone(i))\n {\n i--;\n }\n }\n }\n \n deleteInstrument()\n {\n this.instrumentZones.forEach(z => z.deleteZone());\n this.instrumentZones.length = 0;\n }\n \n /**\n * @param index {number}\n * @returns {boolean} is the zone has been deleted\n */\n safeDeleteZone(index)\n {\n this.instrumentZones[index].useCount--;\n if (this.instrumentZones[index].useCount < 1)\n {\n this.deleteZone(index);\n return true;\n }\n return false;\n }\n \n /**\n * @param index {number}\n */\n deleteZone(index)\n {\n this.instrumentZones[index].deleteZone();\n this.instrumentZones.splice(index, 1);\n }\n}", "/**\n * @typedef {{\n * instrumentGenerators: Generator[],\n * presetGenerators: Generator[],\n * modulators: Modulator[],\n * sample: BasicSample,\n * sampleID: number,\n * }} SampleAndGenerators\n */\nimport { generatorTypes } from \"./generator.js\";\nimport { Modulator } from \"./modulator.js\";\nimport { isXGDrums } from \"../../utils/xg_hacks.js\";\n\nexport class BasicPreset\n{\n /**\n * The parent soundbank instance\n * Currently used for determining default modulators and XG status\n * @type {BasicSoundBank}\n */\n parentSoundBank;\n \n /**\n * The preset's name\n * @type {string}\n */\n presetName = \"\";\n \n /**\n * The preset's MIDI program number\n * @type {number}\n */\n program = 0;\n \n /**\n * The preset's MIDI bank number\n * @type {number}\n */\n bank = 0;\n \n /**\n * The preset's zones\n * @type {BasicPresetZone[]}\n */\n presetZones = [];\n \n /**\n * Stores already found getSamplesAndGenerators for reuse\n * @type {SampleAndGenerators[][][]}\n */\n foundSamplesAndGenerators = [];\n \n /**\n * unused metadata\n * @type {number}\n */\n library = 0;\n /**\n * unused metadata\n * @type {number}\n */\n genre = 0;\n /**\n * unused metadata\n * @type {number}\n */\n morphology = 0;\n \n /**\n * Creates a new preset representation\n * @param parentSoundBank {BasicSoundBank}\n */\n constructor(parentSoundBank)\n {\n this.parentSoundBank = parentSoundBank;\n for (let i = 0; i < 128; i++)\n {\n this.foundSamplesAndGenerators[i] = [];\n }\n }\n \n /**\n * @param allowXG {boolean}\n * @param allowSFX {boolean}\n * @returns {boolean}\n */\n isDrumPreset(allowXG, allowSFX = false)\n {\n const xg = allowXG && this.parentSoundBank.isXGBank;\n // sfx is not cool\n return this.bank === 128 || (\n xg &&\n (isXGDrums(this.bank) && (this.bank !== 126 || allowSFX))\n );\n }\n \n deletePreset()\n {\n this.presetZones.forEach(z => z.deleteZone());\n this.presetZones.length = 0;\n }\n \n /**\n * @param index {number}\n */\n deleteZone(index)\n {\n this.presetZones[index].deleteZone();\n this.presetZones.splice(index, 1);\n }\n \n // noinspection JSUnusedGlobalSymbols\n /**\n * Preloads all samples (async)\n */\n preload(keyMin, keyMax)\n {\n for (let key = keyMin; key < keyMax + 1; key++)\n {\n for (let velocity = 0; velocity < 128; velocity++)\n {\n this.getSamplesAndGenerators(key, velocity).forEach(samandgen =>\n {\n if (!samandgen.sample.isSampleLoaded)\n {\n samandgen.sample.getAudioData();\n }\n });\n }\n }\n }\n \n /**\n * Preloads a specific key/velocity combo\n * @param key {number}\n * @param velocity {number}\n */\n preloadSpecific(key, velocity)\n {\n this.getSamplesAndGenerators(key, velocity).forEach(samandgen =>\n {\n if (!samandgen.sample.isSampleLoaded)\n {\n samandgen.sample.getAudioData();\n }\n });\n }\n \n /**\n * Returns generatorTranslator and generators for given note\n * @param midiNote {number}\n * @param velocity {number}\n * @returns {SampleAndGenerators[]}\n */\n getSamplesAndGenerators(midiNote, velocity)\n {\n const memorized = this.foundSamplesAndGenerators[midiNote][velocity];\n if (memorized)\n {\n return memorized;\n }\n \n if (this.presetZones.length < 1)\n {\n return [];\n }\n \n /**\n * @param range {SoundFontRange}\n * @param number {number}\n * @returns {boolean}\n */\n function isInRange(range, number)\n {\n return number >= range.min && number <= range.max;\n }\n \n /**\n * @param main {Generator[]}\n * @param adder {Generator[]}\n */\n function addUnique(main, adder)\n {\n main.push(...adder.filter(g => !main.find(mg => mg.generatorType === g.generatorType)));\n }\n \n /**\n * @param main {Modulator[]}\n * @param adder {Modulator[]}\n */\n function addUniqueMods(main, adder)\n {\n main.push(...adder.filter(m => !main.find(mm => Modulator.isIdentical(m, mm))));\n }\n \n /**\n * @type {SampleAndGenerators[]}\n */\n let parsedGeneratorsAndSamples = [];\n \n /**\n * global zone is always first, so it or nothing\n * @type {Generator[]}\n */\n let globalPresetGenerators = this.presetZones[0].isGlobal ? [...this.presetZones[0].generators] : [];\n \n /**\n * @type {Modulator[]}\n */\n let globalPresetModulators = this.presetZones[0].isGlobal ? [...this.presetZones[0].modulators] : [];\n const globalKeyRange = this.presetZones[0].isGlobal ? this.presetZones[0].keyRange : { min: 0, max: 127 };\n const globalVelRange = this.presetZones[0].isGlobal ? this.presetZones[0].velRange : { min: 0, max: 127 };\n \n // find the preset zones in range\n let presetZonesInRange = this.presetZones.filter(currentZone =>\n (\n isInRange(\n currentZone.hasKeyRange ? currentZone.keyRange : globalKeyRange,\n midiNote\n )\n &&\n isInRange(\n currentZone.hasVelRange ? currentZone.velRange : globalVelRange,\n velocity\n )\n ) && !currentZone.isGlobal);\n \n presetZonesInRange.forEach(zone =>\n {\n // the global zone is already taken into account earlier\n if (zone.instrument.instrumentZones.length < 1)\n {\n return;\n }\n let presetGenerators = zone.generators;\n let presetModulators = zone.modulators;\n const firstZone = zone.instrument.instrumentZones[0];\n /**\n * global zone is always first, so it or nothing\n * @type {Generator[]}\n */\n let globalInstrumentGenerators = firstZone.isGlobal ? [...firstZone.generators] : [];\n let globalInstrumentModulators = firstZone.isGlobal ? [...firstZone.modulators] : [];\n const globalKeyRange = firstZone.isGlobal ? firstZone.keyRange : { min: 0, max: 127 };\n const globalVelRange = firstZone.isGlobal ? firstZone.velRange : { min: 0, max: 127 };\n \n \n let instrumentZonesInRange = zone.instrument.instrumentZones\n .filter(currentZone =>\n (\n isInRange(\n currentZone.hasKeyRange ? currentZone.keyRange : globalKeyRange,\n midiNote\n )\n &&\n isInRange(\n currentZone.hasVelRange ? currentZone.velRange : globalVelRange,\n velocity\n )\n ) && !currentZone.isGlobal\n );\n \n instrumentZonesInRange.forEach(instrumentZone =>\n {\n let instrumentGenerators = [...instrumentZone.generators];\n let instrumentModulators = [...instrumentZone.modulators];\n \n addUnique(\n presetGenerators,\n globalPresetGenerators\n );\n // add the unique global preset generators (local replace global(\n \n \n // add the unique global instrument generators (local replace global)\n addUnique(\n instrumentGenerators,\n globalInstrumentGenerators\n );\n \n addUniqueMods(\n presetModulators,\n globalPresetModulators\n );\n addUniqueMods(\n instrumentModulators,\n globalInstrumentModulators\n );\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 * @type {Modulator[]}\n */\n const finalModulatorList = [...instrumentModulators];\n for (let i = 0; i < presetModulators.length; i++)\n {\n let mod = presetModulators[i];\n const identicalInstrumentModulator = finalModulatorList.findIndex(\n m => Modulator.isIdentical(mod, m));\n if (identicalInstrumentModulator !== -1)\n {\n // sum the amounts\n // (this makes a new modulator because otherwise it would overwrite the one in the soundfont!\n finalModulatorList[identicalInstrumentModulator] = finalModulatorList[identicalInstrumentModulator].sumTransform(\n mod);\n }\n else\n {\n finalModulatorList.push(mod);\n }\n }\n \n \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 sampleID: instrumentZone.generators.find(\n g => g.generatorType === generatorTypes.sampleID).generatorValue\n });\n });\n });\n \n // save and return\n this.foundSamplesAndGenerators[midiNote][velocity] = parsedGeneratorsAndSamples;\n return parsedGeneratorsAndSamples;\n }\n}", "import {\n SpessaSynthGroup,\n SpessaSynthGroupCollapsed,\n SpessaSynthGroupEnd,\n SpessaSynthInfo,\n SpessaSynthWarn\n} from \"../../utils/loggin.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { write } from \"./write_sf2/write.js\";\nimport { defaultModulators, Modulator } from \"./modulator.js\";\nimport { writeDLS } from \"./write_dls/write_dls.js\";\nimport { BasicSample } from \"./basic_sample.js\";\nimport { BasicInstrumentZone, BasicPresetZone } from \"./basic_zones.js\";\nimport { Generator, generatorTypes } from \"./generator.js\";\nimport { BasicInstrument } from \"./basic_instrument.js\";\nimport { BasicPreset } from \"./basic_preset.js\";\nimport { isXGDrums } from \"../../utils/xg_hacks.js\";\n\nclass BasicSoundBank\n{\n \n /**\n * Soundfont's info stored as name: value. ifil and iver are stored as string representation of float (e.g., 2.1)\n * @type {Object<string, string|IndexedByteArray>}\n */\n soundFontInfo = {};\n \n /**\n * The soundfont's presets\n * @type {BasicPreset[]}\n */\n presets = [];\n \n /**\n * The soundfont's samples\n * @type {BasicSample[]}\n */\n samples = [];\n \n /**\n * The soundfont's instruments\n * @type {BasicInstrument[]}\n */\n instruments = [];\n \n /**\n * Soundfont's default modulatorss\n * @type {Modulator[]}\n */\n defaultModulators = defaultModulators.map(m => Modulator.copy(m));\n \n /**\n * Checks for XG drumsets and considers if this soundfont is XG.\n * @type {boolean}\n */\n isXGBank = false;\n \n /**\n * Creates a new basic soundfont template\n * @param data {undefined|{presets: BasicPreset[], info: Object<string, string>}}\n */\n constructor(data = undefined)\n {\n if (data?.presets)\n {\n this.presets.push(...data.presets);\n this.soundFontInfo = data.info;\n }\n }\n \n /**\n * Merges soundfonts with the given order. Keep in mind that the info read is copied from the first one\n * @param soundfonts {...BasicSoundBank} the soundfonts to merge, the first overwrites the last\n * @returns {BasicSoundBank}\n */\n static mergeSoundBanks(...soundfonts)\n {\n const mainSf = soundfonts.shift();\n const presets = mainSf.presets;\n while (soundfonts.length)\n {\n const newPresets = soundfonts.shift().presets;\n newPresets.forEach(newPreset =>\n {\n if (\n presets.find(existingPreset => existingPreset.bank === newPreset.bank && existingPreset.program === newPreset.program) === undefined\n )\n {\n presets.push(newPreset);\n }\n });\n }\n \n return new BasicSoundBank({ presets: presets, info: mainSf.soundFontInfo });\n }\n \n /**\n * Creates a simple soundfont with one saw wave preset.\n * @returns {ArrayBufferLike}\n */\n static getDummySoundfontFile()\n {\n const font = new BasicSoundBank();\n const sample = new BasicSample(\n \"Saw\",\n 44100,\n 65,\n 20,\n 0,\n 0,\n 0,\n 127\n );\n sample.sampleData = new Float32Array(128);\n for (let i = 0; i < 128; i++)\n {\n sample.sampleData[i] = (i / 128) * 2 - 1;\n }\n font.samples.push(sample);\n \n const gZone = new BasicInstrumentZone();\n gZone.isGlobal = true;\n gZone.generators.push(new Generator(generatorTypes.initialAttenuation, 375));\n gZone.generators.push(new Generator(generatorTypes.releaseVolEnv, -1000));\n gZone.generators.push(new Generator(generatorTypes.sampleModes, 1));\n \n const zone1 = new BasicInstrumentZone();\n zone1.sample = sample;\n \n const zone2 = new BasicInstrumentZone();\n zone2.sample = sample;\n zone2.generators.push(new Generator(generatorTypes.fineTune, -9));\n \n \n const inst = new BasicInstrument();\n inst.instrumentName = \"Saw Wave\";\n inst.instrumentZones.push(gZone);\n inst.instrumentZones.push(zone1);\n inst.instrumentZones.push(zone2);\n font.instruments.push(inst);\n \n const pZone = new BasicPresetZone();\n pZone.instrument = inst;\n \n const preset = new BasicPreset(font);\n preset.presetName = \"Saw Wave\";\n preset.presetZones.push(pZone);\n font.presets.push(preset);\n \n font.soundFontInfo[\"ifil\"] = \"2.1\";\n font.soundFontInfo[\"isng\"] = \"EMU8000\";\n font.soundFontInfo[\"INAM\"] = \"Dummy\";\n font._parseInternal();\n return font.write().buffer;\n }\n \n /**\n * parses the bank after loading is done\n * @protected\n */\n _parseInternal()\n {\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 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 24,\n // 25, 27, 28, 29, 30, 31, 32, 33, 40, 41, 48, 56, 57, 58,\n // 64, 65, 66, 126, 127\n const allowedPrograms = new Set([\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 24,\n 25, 27, 28, 29, 30, 31, 32, 33, 40, 41, 48, 56, 57, 58,\n 64, 65, 66, 126, 127\n ]);\n for (const preset of this.presets)\n {\n if (isXGDrums(preset.bank))\n {\n this.isXGBank = true;\n if (!allowedPrograms.has(preset.program))\n {\n // not valid!\n this.isXGBank = false;\n SpessaSynthInfo(\n `%cThis bank is not valid XG. Preset %c${preset.bank}:${preset.program}%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 /**\n * Trims a sound bank to only contain samples in a given MIDI file\n * @param mid {BasicMIDI} - the MIDI file\n */\n trimSoundBank(mid)\n {\n const soundfont = this;\n \n /**\n * @param instrument {Instrument}\n * @param combos {{key: number, velocity: number}[]}\n * @returns {number}\n */\n function trimInstrumentZones(instrument, combos)\n {\n let trimmedIZones = 0;\n for (let iZoneIndex = 0; iZoneIndex < instrument.instrumentZones.length; iZoneIndex++)\n {\n const iZone = instrument.instrumentZones[iZoneIndex];\n if (iZone.isGlobal)\n {\n continue;\n }\n const iKeyRange = iZone.keyRange;\n const iVelRange = iZone.velRange;\n let isIZoneUsed = false;\n for (const iCombo of combos)\n {\n if (\n (iCombo.key >= iKeyRange.min && iCombo.key <= iKeyRange.max) &&\n (iCombo.velocity >= iVelRange.min && iCombo.velocity <= iVelRange.max)\n )\n {\n isIZoneUsed = true;\n break;\n }\n }\n if (!isIZoneUsed)\n {\n SpessaSynthInfo(\n `%c${iZone.sample.sampleName} %cremoved from %c${instrument.instrumentName}%c. Use count: %c${iZone.useCount - 1}`,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n if (instrument.safeDeleteZone(iZoneIndex))\n {\n trimmedIZones++;\n iZoneIndex--;\n SpessaSynthInfo(\n `%c${iZone.sample.sampleName} %cdeleted`,\n consoleColors.recognized,\n consoleColors.info\n );\n }\n if (iZone.sample.useCount < 1)\n {\n soundfont.deleteSample(iZone.sample);\n }\n }\n \n }\n return trimmedIZones;\n }\n \n SpessaSynthGroup(\n \"%cTrimming soundfont...\",\n consoleColors.info\n );\n const usedProgramsAndKeys = mid.getUsedProgramsAndKeys(soundfont);\n \n SpessaSynthGroupCollapsed(\n \"%cModifying soundfont...\",\n consoleColors.info\n );\n SpessaSynthInfo(\"Detected keys for midi:\", usedProgramsAndKeys);\n // modify the soundfont to only include programs and samples that are used\n for (let presetIndex = 0; presetIndex < soundfont.presets.length; presetIndex++)\n {\n const p = soundfont.presets[presetIndex];\n const string = p.bank + \":\" + p.program;\n const used = usedProgramsAndKeys[string];\n if (used === undefined)\n {\n SpessaSynthInfo(\n `%cDeleting preset %c${p.presetName}%c and its zones`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n soundfont.deletePreset(p);\n presetIndex--;\n }\n else\n {\n const combos = [...used].map(s =>\n {\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.presetName}`,\n consoleColors.info,\n consoleColors.recognized\n );\n SpessaSynthInfo(`Keys for ${p.presetName}:`, combos);\n let trimmedZones = 0;\n // clean the preset to only use zones that are used\n for (let zoneIndex = 0; zoneIndex < p.presetZones.length; zoneIndex++)\n {\n const zone = p.presetZones[zoneIndex];\n if (zone.isGlobal)\n {\n continue;\n }\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 {\n if (\n (combo.key >= keyRange.min && combo.key <= keyRange.max) &&\n (combo.velocity >= velRange.min && combo.velocity <= velRange.max)\n )\n {\n // zone is used, trim the instrument zones\n isZoneUsed = true;\n const trimmedIZones = trimInstrumentZones(zone.instrument, combos);\n SpessaSynthInfo(\n `%cTrimmed off %c${trimmedIZones}%c zones from %c${zone.instrument.instrumentName}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n break;\n }\n }\n if (!isZoneUsed)\n {\n trimmedZones++;\n p.deleteZone(zoneIndex);\n if (zone.instrument.useCount < 1)\n {\n soundfont.deleteInstrument(zone.instrument);\n }\n zoneIndex--;\n }\n }\n SpessaSynthInfo(\n `%cTrimmed off %c${trimmedZones}%c zones from %c${p.presetName}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n SpessaSynthGroupEnd();\n }\n }\n soundfont.removeUnusedElements();\n \n soundfont.soundFontInfo[\"ICMT\"] = `NOTE: This soundfont was trimmed by SpessaSynth to only contain presets used in \"${mid.midiName}\"\\n\\n`\n + soundfont.soundFontInfo[\"ICMT\"];\n \n SpessaSynthInfo(\n \"%cSoundfont modified!\",\n consoleColors.recognized\n );\n SpessaSynthGroupEnd();\n SpessaSynthGroupEnd();\n }\n \n removeUnusedElements()\n {\n this.instruments.forEach(i =>\n {\n if (i.useCount < 1)\n {\n i.instrumentZones.forEach(z =>\n {\n if (!z.isGlobal)\n {\n z.sample.useCount--;\n }\n });\n }\n });\n this.instruments = this.instruments.filter(i => i.useCount > 0);\n this.samples = this.samples.filter(s => s.useCount > 0);\n }\n \n /**\n * @param instrument {BasicInstrument}\n */\n deleteInstrument(instrument)\n {\n if (instrument.useCount > 0)\n {\n throw new Error(`Cannot delete an instrument that has ${instrument.useCount} usages.`);\n }\n this.instruments.splice(this.instruments.indexOf(instrument), 1);\n instrument.deleteInstrument();\n this.removeUnusedElements();\n }\n \n /**\n * @param preset {BasicPreset}\n */\n deletePreset(preset)\n {\n preset.deletePreset();\n this.presets.splice(this.presets.indexOf(preset), 1);\n this.removeUnusedElements();\n }\n \n /**\n * @param sample {BasicSample}\n */\n deleteSample(sample)\n {\n if (sample.useCount > 0)\n {\n throw new Error(`Cannot delete sample that has ${sample.useCount} usages.`);\n }\n this.samples.splice(this.samples.indexOf(sample), 1);\n this.removeUnusedElements();\n }\n \n /**\n * Get the appropriate preset, undefined if not found\n * @param bankNr {number}\n * @param programNr {number}\n * @param allowXGDrums {boolean} if true, allows XG drum banks (120, 126 and 127) as drum preset\n * @return {BasicPreset}\n */\n getPresetNoFallback(bankNr, programNr, allowXGDrums = false)\n {\n const isDrum = bankNr === 128 || (allowXGDrums && isXGDrums(bankNr));\n // check for exact match\n let p;\n if (isDrum)\n {\n p = this.presets.find(p => p.bank === bankNr && p.isDrumPreset(allowXGDrums) && p.program === programNr);\n }\n else\n {\n p = this.presets.find(p => p.bank === bankNr && p.program === programNr);\n }\n if (p)\n {\n return p;\n }\n // no match...\n if (isDrum)\n {\n if (allowXGDrums)\n {\n // try any drum preset with matching program?\n const p = this.presets.find(p => p.isDrumPreset(allowXGDrums) && p.program === programNr);\n if (p)\n {\n return p;\n }\n }\n }\n return undefined;\n }\n \n /**\n * Get the appropriate preset\n * @param bankNr {number}\n * @param programNr {number}\n * @param allowXGDrums {boolean} if true, allows XG drum banks (120, 126 and 127) as drum preset\n * @returns {BasicPreset}\n */\n getPreset(bankNr, programNr, allowXGDrums = false)\n {\n const isDrums = bankNr === 128 || (allowXGDrums && isXGDrums(bankNr));\n // check for exact match\n let preset;\n // only allow drums if the preset is considered to be a drum preset\n if (isDrums)\n {\n preset = this.presets.find(p => p.bank === bankNr && p.isDrumPreset(allowXGDrums) && p.program === programNr);\n }\n else\n {\n preset = this.presets.find(p => p.bank === bankNr && p.program === programNr);\n }\n if (preset)\n {\n return preset;\n }\n // no match...\n if (isDrums)\n {\n // drum preset: find any preset with bank 128\n preset = this.presets.find(p => p.isDrumPreset(allowXGDrums) && p.program === programNr);\n if (!preset)\n {\n // only allow 128, otherwise it would default to XG SFX\n preset = this.presets.find(p => p.isDrumPreset(allowXGDrums));\n }\n }\n else\n {\n // non-drum preset: find any preset with the given program that is not a drum preset\n preset = this.presets.find(p => p.program === programNr && !p.isDrumPreset(allowXGDrums));\n }\n if (preset)\n {\n SpessaSynthWarn(\n `%cPreset ${bankNr}.${programNr} not found. Replaced with %c${preset.presetName} (${preset.bank}.${preset.program})`,\n consoleColors.warn,\n consoleColors.recognized\n );\n }\n \n // no preset, use the first one available\n if (!preset)\n {\n SpessaSynthWarn(`Preset ${programNr} not found. Defaulting to`, this.presets[0].presetName);\n preset = this.presets[0];\n }\n return preset;\n }\n \n /**\n * gets preset by name\n * @param presetName {string}\n * @returns {BasicPreset}\n */\n getPresetByName(presetName)\n {\n let preset = this.presets.find(p => p.presetName === presetName);\n if (!preset)\n {\n SpessaSynthWarn(\"Preset not found. Defaulting to:\", this.presets[0].presetName);\n preset = this.presets[0];\n }\n return preset;\n }\n \n /**\n * @param error {string}\n */\n parsingError(error)\n {\n throw new Error(`SF parsing error: ${error} The file may be corrupted.`);\n }\n \n destroySoundBank()\n {\n delete this.presets;\n delete this.instruments;\n delete this.samples;\n }\n}\n\nBasicSoundBank.prototype.write = write;\nBasicSoundBank.prototype.writeDLS = writeDLS;\n\nexport { BasicSoundBank };", "import { readRIFFChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from \"../../utils/loggin.js\";\nimport { consoleColors } from \"../../utils/other.js\";\n\n/**\n * @this {DLSSoundFont}\n * @param instrumentListChunk {RiffChunk}\n */\nexport function readDLSInstrumentList(instrumentListChunk)\n{\n SpessaSynthGroupCollapsed(\"%cLoading instruments...\", consoleColors.info);\n for (let i = 0; i < this.instrumentAmount; i++)\n {\n this.readDLSInstrument(readRIFFChunk(instrumentListChunk.chunkData));\n }\n SpessaSynthGroupEnd();\n}", "import { BasicPreset } from \"../basic_soundfont/basic_preset.js\";\nimport { BasicPresetZone } from \"../basic_soundfont/basic_zones.js\";\nimport { BasicInstrument } from \"../basic_soundfont/basic_instrument.js\";\n\nexport class DLSPreset extends BasicPreset\n{\n /**\n * Creates a new DLS preset\n * @param dls {BasicSoundBank}\n * @param ulBank {number}\n * @param ulInstrument {number}\n */\n constructor(dls, ulBank, ulInstrument)\n {\n // use stock default modulators, dls won't ever have DMOD chunk\n super(dls);\n this.program = ulInstrument & 127;\n const bankMSB = (ulBank >> 8) & 127;\n const bankLSB = ulBank & 127;\n // switch accordingly\n if (bankMSB > 0)\n {\n this.bank = bankMSB;\n }\n else\n {\n this.bank = bankLSB;\n }\n const isDrums = ulBank >> 31;\n if (isDrums)\n {\n // soundfont bank is 128, so we change it here\n this.bank = 128;\n }\n \n this.DLSInstrument = new BasicInstrument();\n this.DLSInstrument.addUseCount();\n \n const zone = new BasicPresetZone();\n zone.instrument = this.DLSInstrument;\n \n this.presetZones = [zone];\n }\n}", "import { readBytesAsString } from \"../../utils/byte_functions/string.js\";\nimport { readLittleEndian } from \"../../utils/byte_functions/little_endian.js\";\nimport { DLSPreset } from \"./dls_preset.js\";\nimport { findRIFFListType, readRIFFChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from \"../../utils/loggin.js\";\nimport { BasicInstrumentZone } from \"../basic_soundfont/basic_zones.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { generatorLimits, generatorTypes } from \"../basic_soundfont/generator.js\";\nimport { Modulator } from \"../basic_soundfont/modulator.js\";\nimport { DEFAULT_DLS_CHORUS, DEFAULT_DLS_REVERB } from \"./dls_sources.js\";\n\n/**\n * @this {DLSSoundFont}\n * @param chunk {RiffChunk}\n */\nexport function readDLSInstrument(chunk)\n{\n this.verifyHeader(chunk, \"LIST\");\n this.verifyText(readBytesAsString(chunk.chunkData, 4), \"ins \");\n /**\n * @type {RiffChunk[]}\n */\n const chunks = [];\n while (chunk.chunkData.length > chunk.chunkData.currentIndex)\n {\n chunks.push(readRIFFChunk(chunk.chunkData));\n }\n \n \n const instrumentHeader = chunks.find(c => c.header === \"insh\");\n if (!instrumentHeader)\n {\n SpessaSynthGroupEnd();\n throw new Error(\"No instrument header!\");\n }\n \n // read instrument header\n const regions = readLittleEndian(instrumentHeader.chunkData, 4);\n const ulBank = readLittleEndian(instrumentHeader.chunkData, 4);\n const ulInstrument = readLittleEndian(instrumentHeader.chunkData, 4);\n const preset = new DLSPreset(this, ulBank, ulInstrument);\n \n // read preset name in INFO\n let presetName = \"unnamedPreset\";\n const infoChunk = findRIFFListType(chunks, \"INFO\");\n if (infoChunk)\n {\n let info = readRIFFChunk(infoChunk.chunkData);\n while (info.header !== \"INAM\")\n {\n info = readRIFFChunk(infoChunk.chunkData);\n }\n presetName = readBytesAsString(info.chunkData, info.chunkData.length).trim();\n }\n preset.presetName = presetName;\n preset.DLSInstrument.instrumentName = presetName;\n SpessaSynthGroupCollapsed(\n `%cParsing %c\"${presetName}\"%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 {\n SpessaSynthGroupEnd();\n throw new Error(\"No region list!\");\n }\n \n // global articulation: essentially global zone\n const globalZone = new BasicInstrumentZone();\n globalZone.isGlobal = true;\n \n // read articulators\n const globalLart = findRIFFListType(chunks, \"lart\");\n const globalLar2 = findRIFFListType(chunks, \"lar2\");\n if (globalLar2 !== undefined || globalLart !== undefined)\n {\n this.readLart(globalLart, globalLar2, globalZone);\n }\n // remove generators with default values\n globalZone.generators = globalZone.generators.filter(g => g.generatorValue !== generatorLimits[g.generatorType].def);\n // override reverb and chorus with 1000 instead of 200 (if not override)\n // reverb\n if (globalZone.modulators.find(m => m.modulatorDestination === generatorTypes.reverbEffectsSend) === undefined)\n {\n globalZone.modulators.push(Modulator.copy(DEFAULT_DLS_REVERB));\n }\n // chorus\n if (globalZone.modulators.find(m => m.modulatorDestination === generatorTypes.chorusEffectsSend) === undefined)\n {\n globalZone.modulators.push(Modulator.copy(DEFAULT_DLS_CHORUS));\n }\n preset.DLSInstrument.instrumentZones.push(globalZone);\n \n // read regions\n for (let i = 0; i < regions; i++)\n {\n const chunk = readRIFFChunk(regionListChunk.chunkData);\n this.verifyHeader(chunk, \"LIST\");\n const type = readBytesAsString(chunk.chunkData, 4);\n if (type !== \"rgn \" && type !== \"rgn2\")\n {\n SpessaSynthGroupEnd();\n this.parsingError(`Invalid DLS region! Expected \"rgn \" or \"rgn2\" got \"${type}\"`);\n }\n \n \n const zone = this.readRegion(chunk);\n if (zone)\n {\n preset.DLSInstrument.instrumentZones.push(zone);\n }\n }\n \n this.presets.push(preset);\n this.instruments.push(preset.DLSInstrument);\n SpessaSynthGroupEnd();\n}", "import { DLSSources } from \"./dls_sources.js\";\nimport { getModSourceEnum, Modulator, modulatorCurveTypes, modulatorSources } from \"../basic_soundfont/modulator.js\";\nimport { midiControllers } from \"../../midi/midi_message.js\";\nimport { DLSDestinations } from \"./dls_destinations.js\";\n\nimport { generatorTypes } from \"../basic_soundfont/generator.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { SpessaSynthWarn } from \"../../utils/loggin.js\";\n\n/**\n * @param source {number}\n * @returns {{enum: number, isCC: boolean}|undefined}\n */\nfunction getSF2SourceFromDLS(source)\n{\n let sourceEnum = undefined;\n let isCC = false;\n switch (source)\n {\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 {\n throw new Error(`Unknown DLS Source: ${source}`);\n }\n return { enum: sourceEnum, isCC: isCC };\n}\n\n/**\n * @param destination {number}\n * @param amount {number}\n * @returns {generatorTypes|{gen: generatorTypes, newAmount: number}} // transform amount to sf2 units\n */\nfunction getSF2GeneratorFromDLS(destination, amount)\n{\n switch (destination)\n {\n default:\n case DLSDestinations.none:\n return undefined;\n case DLSDestinations.pan:\n return generatorTypes.pan;\n case DLSDestinations.gain:\n return { gen: generatorTypes.initialAttenuation, newAmount: amount * -1 };\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 { gen: generatorTypes.sustainVolEnv, newAmount: 1000 - amount };\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 { gen: generatorTypes.sustainModEnv, newAmount: (1000 - amount) / 10 };\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/**\n * checks for combos such as mod lfo as source and pitch as destination which results in modLfoToPitch\n * @param source {number}\n * @param destination {number}\n * @returns {generatorTypes} real destination\n */\nfunction checkForSpecialDLSCombo(source, destination)\n{\n if (source === DLSSources.vibratoLfo && destination === DLSDestinations.pitch)\n {\n // vibrato lfo to pitch\n return generatorTypes.vibLfoToPitch;\n }\n else if (source === DLSSources.modLfo && destination === DLSDestinations.pitch)\n {\n // mod lfo to pitch\n return generatorTypes.modLfoToPitch;\n }\n else if (source === DLSSources.modLfo && destination === DLSDestinations.filterCutoff)\n {\n // mod lfo to filter\n return generatorTypes.modLfoToFilterFc;\n }\n else if (source === DLSSources.modLfo && destination === DLSDestinations.gain)\n {\n // mod lfo to volume\n return generatorTypes.modLfoToVolume;\n }\n else if (source === DLSSources.modEnv && destination === DLSDestinations.filterCutoff)\n {\n // mod envelope to filter\n return generatorTypes.modEnvToFilterFc;\n }\n else if (source === DLSSources.modEnv && destination === DLSDestinations.pitch)\n {\n // mod envelope to pitch\n return generatorTypes.modEnvToPitch;\n }\n else\n {\n return undefined;\n }\n}\n\n// noinspection JSUnusedGlobalSymbols\n/**\n * @param source {number}\n * @param control {number}\n * @param destination {number}\n * @param value {number}\n * @param transform {number}\n * @param msg {string}\n */\nexport function modulatorConverterDebug(\n source,\n control,\n destination,\n value,\n transform,\n msg = \"Attempting to convert the following DLS Articulator to SF2 Modulator:\"\n)\n{\n const type = Object.keys(DLSDestinations).find(k => DLSDestinations[k] === destination);\n const srcType = Object.keys(DLSSources).find(k => DLSSources[k] === source);\n const ctrlType = Object.keys(DLSSources).find(k => DLSSources[k] === control);\n const typeString = type ? type : destination.toString(16);\n const srcString = srcType ? srcType : source.toString(16);\n const ctrlString = ctrlType ? ctrlType : control.toString(16);\n console.debug(\n `%c${msg}\n Source: %c${srcString}%c\n Control: %c${ctrlString}%c\n Destination: %c${typeString}%c\n Amount: %c${value}%c\n Transform: %c${transform}%c...`,\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 consoleColors.recognized,\n consoleColors.info\n );\n}\n\n/**\n * @param source {number}\n * @param control {number}\n * @param destination {number}\n * @param transform {number}\n * @param value {number}\n * @returns {Modulator|undefined}\n */\nexport function getSF2ModulatorFromArticulator(\n source,\n control,\n destination,\n transform,\n value\n)\n{\n // modulatorConverterDebug(\n // source,\n // control,\n // destination,\n // value,\n // transform\n // );\n // check for special combinations\n const specialDestination = checkForSpecialDLSCombo(source, destination);\n /**\n * @type {generatorTypes}\n */\n let destinationGenerator;\n /**\n * @type {{enum: number, isCC: boolean}}\n */\n let sf2Source;\n let swapSources = false;\n let isSourceNoController = false;\n let newValue = value;\n if (specialDestination === undefined)\n {\n // determine destination\n const sf2GenDestination = getSF2GeneratorFromDLS(destination, value);\n if (sf2GenDestination === undefined)\n {\n // cannot be a valid modulator\n SpessaSynthWarn(`Invalid destination: ${destination}`);\n return undefined;\n }\n /**\n * @type {generatorTypes}\n */\n destinationGenerator = sf2GenDestination;\n if (sf2GenDestination.newAmount !== undefined)\n {\n newValue = sf2GenDestination.newAmount;\n destinationGenerator = sf2GenDestination.gen;\n }\n sf2Source = getSF2SourceFromDLS(source);\n if (sf2Source === undefined)\n {\n // cannot be a valid modulator\n SpessaSynthWarn(`Invalid source: ${source}`);\n return undefined;\n }\n }\n else\n {\n destinationGenerator = specialDestination;\n swapSources = true;\n sf2Source = { enum: modulatorSources.noController, isCC: false };\n isSourceNoController = true;\n }\n let sf2SecondSource = getSF2SourceFromDLS(control);\n if (sf2SecondSource === undefined)\n {\n // cannot be a valid modulator\n SpessaSynthWarn(`Invalid control: ${control}`);\n return undefined;\n }\n \n // get transforms and final enums\n let sourceEnumFinal;\n if (isSourceNoController)\n {\n // we force it into this state because before it was some strange value,\n // like vibrato lfo bipolar, for example,\n // since we turn it into NoController -> vibLfoToPitch,\n // the result is the same and bipolar controller is technically 0\n sourceEnumFinal = 0x0;\n }\n else\n {\n // output transform is ignored as it's not a thing in sfont format\n // unless the curve type of source is linear, then output is copied\n const outputTransform = transform & 0b1111;\n // source curve type maps to a desfont curve type in section 2.10, table 9\n let sourceTransform = (transform >> 10) & 0b1111;\n if (sourceTransform === modulatorCurveTypes.linear && outputTransform !== modulatorCurveTypes.linear)\n {\n sourceTransform = outputTransform;\n }\n const sourceIsBipolar = (transform >> 14) & 1;\n let sourceIsNegative = (transform >> 15) & 1;\n // special case: for attenuation, invert source (dls gain is the opposite of sf2 attenuation)\n if (destinationGenerator === generatorTypes.initialAttenuation)\n {\n // if the value is negative, the source shall be negative!\n // why?\n // IDK, it makes it work with ROCK.RMI and NOKIA_S30.dls\n if (value < 0)\n {\n sourceIsNegative = 1;\n }\n }\n sourceEnumFinal = getModSourceEnum(\n sourceTransform,\n sourceIsBipolar,\n sourceIsNegative,\n sf2Source.isCC,\n sf2Source.enum\n );\n }\n \n // a corrupted rendition of gm.dls was found under\n // https://sembiance.com/fileFormatSamples/audio/downloadableSoundBank/\n // which specifies a whopping -32,768 decibels of attenuation\n if (destinationGenerator === generatorTypes.initialAttenuation)\n {\n newValue = Math.max(960, Math.min(0, newValue));\n }\n \n const secSourceTransform = (transform >> 4) & 0b1111;\n const secSourceIsBipolar = (transform >> 8) & 1;\n const secSourceIsNegative = transform >> 9 & 1;\n let secSourceEnumFinal = getModSourceEnum(\n secSourceTransform,\n secSourceIsBipolar,\n secSourceIsNegative,\n sf2SecondSource.isCC,\n sf2SecondSource.enum\n );\n \n if (swapSources)\n {\n const temp = secSourceEnumFinal;\n secSourceEnumFinal = sourceEnumFinal;\n sourceEnumFinal = temp;\n }\n \n // return the modulator!\n return new Modulator(\n sourceEnumFinal,\n secSourceEnumFinal,\n destinationGenerator,\n newValue,\n 0x0\n );\n \n}", "import { readLittleEndian } from \"../../utils/byte_functions/little_endian.js\";\nimport { DLSDestinations } from \"./dls_destinations.js\";\nimport { DLS_1_NO_VIBRATO_MOD, DLS_1_NO_VIBRATO_PRESSURE, DLSSources } from \"./dls_sources.js\";\nimport { getSF2ModulatorFromArticulator } from \"./articulator_converter.js\";\nimport { SpessaSynthInfo, SpessaSynthWarn } from \"../../utils/loggin.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { Generator, generatorTypes } from \"../basic_soundfont/generator.js\";\nimport { Modulator } from \"../basic_soundfont/modulator.js\";\n\n\n/**\n * Reads the articulator chunk\n * @param chunk {RiffChunk}\n * @param disableVibrato {boolean} it seems that dls 1 does not have vibrato lfo, so we shall disable it\n * @returns {{modulators: Modulator[], generators: Generator[]}}\n */\nexport function readArticulation(chunk, disableVibrato)\n{\n const artData = chunk.chunkData;\n /**\n * @type {Generator[]}\n */\n const generators = [];\n /**\n * @type {Modulator[]}\n */\n const modulators = [];\n \n // cbSize (ignore)\n readLittleEndian(artData, 4);\n const connectionsAmount = readLittleEndian(artData, 4);\n for (let i = 0; i < connectionsAmount; i++)\n {\n // read the block\n const source = readLittleEndian(artData, 2);\n const control = readLittleEndian(artData, 2);\n const destination = readLittleEndian(artData, 2);\n const transform = readLittleEndian(artData, 2);\n const scale = readLittleEndian(artData, 4) | 0;\n const value = scale >> 16; // convert it to 16 bit as soundfont uses that\n \n // modulatorConverterDebug(\n // source,\n // control,\n // destination,\n // value,\n // transform\n // );\n \n // interpret this somehow...\n // if source and control are both zero, it's a generator\n if (source === 0 && control === 0 && transform === 0)\n {\n /**\n * @type {Generator}\n */\n let generator;\n switch (destination)\n {\n case DLSDestinations.pan:\n generator = new Generator(generatorTypes.pan, value); // turn percent into tenths of percent\n break;\n case DLSDestinations.gain:\n generator = new Generator(generatorTypes.initialAttenuation, -value * 10 / 0.4); // turn to centibels and apply emu correction\n break;\n case DLSDestinations.filterCutoff:\n generator = new Generator(generatorTypes.initialFilterFc, value);\n break;\n case DLSDestinations.filterQ:\n generator = new Generator(generatorTypes.initialFilterQ, value);\n break;\n \n // mod lfo raw values it seems\n case DLSDestinations.modLfoFreq:\n generator = new Generator(generatorTypes.freqModLFO, value);\n break;\n case DLSDestinations.modLfoDelay:\n generator = new Generator(generatorTypes.delayModLFO, value);\n break;\n case DLSDestinations.vibLfoFreq:\n generator = new Generator(generatorTypes.freqVibLFO, value);\n break;\n case DLSDestinations.vibLfoDelay:\n generator = new Generator(generatorTypes.delayVibLFO, value);\n break;\n \n // vol. env: all times are timecents like sf2\n case DLSDestinations.volEnvDelay:\n generator = new Generator(generatorTypes.delayVolEnv, value);\n break;\n case DLSDestinations.volEnvAttack:\n generator = new Generator(generatorTypes.attackVolEnv, value);\n break;\n case DLSDestinations.volEnvHold:\n // do not validate because keyNumToSomething\n generator = new Generator(generatorTypes.holdVolEnv, value, false);\n break;\n case DLSDestinations.volEnvDecay:\n // do not validate because keyNumToSomething\n generator = new Generator(generatorTypes.decayVolEnv, value, false);\n break;\n case DLSDestinations.volEnvRelease:\n generator = new Generator(generatorTypes.releaseVolEnv, value);\n break;\n case DLSDestinations.volEnvSustain:\n // gain seems to be (1000 - value) / 10 = sustain dB\n const sustainCb = 1000 - value;\n generator = new Generator(generatorTypes.sustainVolEnv, sustainCb);\n break;\n \n // mod env\n case DLSDestinations.modEnvDelay:\n generator = new Generator(generatorTypes.delayModEnv, value);\n break;\n case DLSDestinations.modEnvAttack:\n generator = new Generator(generatorTypes.attackModEnv, value);\n break;\n case DLSDestinations.modEnvHold:\n // do not validate because keyNumToSomething\n generator = new Generator(generatorTypes.holdModEnv, value, false);\n break;\n case DLSDestinations.modEnvDecay:\n // do not validate because keyNumToSomething\n generator = new Generator(generatorTypes.decayModEnv, value, false);\n break;\n case DLSDestinations.modEnvRelease:\n generator = new Generator(generatorTypes.releaseModEnv, value);\n break;\n case DLSDestinations.modEnvSustain:\n // dls uses 1%, desfont uses 0.1%\n const percentageSustain = 1000 - value;\n generator = new Generator(generatorTypes.sustainModEnv, percentageSustain);\n break;\n \n case DLSDestinations.reverbSend:\n generator = new Generator(generatorTypes.reverbEffectsSend, value);\n break;\n case DLSDestinations.chorusSend:\n generator = new Generator(generatorTypes.chorusEffectsSend, value);\n break;\n case DLSDestinations.pitch:\n // split it up\n const semi = Math.floor(value / 100);\n const cents = Math.floor(value - semi * 100);\n generator = new Generator(generatorTypes.fineTune, cents);\n generators.push(new Generator(generatorTypes.coarseTune, semi));\n break;\n }\n if (generator)\n {\n generators.push(generator);\n }\n }\n else\n // if not, modulator?\n {\n let isGenerator = true;\n \n const applyKeyToCorrection = (value, keyToGen, realGen) =>\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 value:\n // real + (60 / 128) * scale\n const keyToGenValue = value / -128;\n generators.push(new Generator(keyToGen, keyToGenValue));\n // airfont 340 fix\n if (keyToGenValue <= 120)\n {\n const correction = Math.round((60 / 128) * value);\n generators.forEach(g =>\n {\n if (g.generatorType === realGen)\n {\n g.generatorValue += correction;\n }\n });\n }\n };\n \n // a few special cases which are generators:\n if (control === DLSSources.none)\n {\n // mod lfo to pitch\n if (source === DLSSources.modLfo && destination === DLSDestinations.pitch)\n {\n generators.push(new Generator(generatorTypes.modLfoToPitch, value));\n }\n else\n // mod lfo to volume\n if (source === DLSSources.modLfo && destination === DLSDestinations.gain)\n {\n generators.push(new Generator(generatorTypes.modLfoToVolume, value));\n }\n else\n // mod lfo to filter\n if (source === DLSSources.modLfo && destination === DLSDestinations.filterCutoff)\n {\n generators.push(new Generator(generatorTypes.modLfoToFilterFc, value));\n }\n else\n // vib lfo to pitch\n if (source === DLSSources.vibratoLfo && destination === DLSDestinations.pitch)\n {\n generators.push(new Generator(generatorTypes.vibLfoToPitch, value));\n }\n else\n // mod env to pitch\n if (source === DLSSources.modEnv && destination === DLSDestinations.pitch)\n {\n generators.push(new Generator(generatorTypes.modEnvToPitch, value));\n }\n else\n // mod env to filter\n if (source === DLSSources.modEnv && destination === DLSDestinations.filterCutoff)\n {\n generators.push(new Generator(generatorTypes.modEnvToFilterFc, value));\n }\n else\n // scale tuning (key number to pitch)\n if (source === DLSSources.keyNum && destination === DLSDestinations.pitch)\n {\n // this is just a soundfont generator, but the amount must be changed\n // 12,800 means the regular scale (100)\n generators.push(new Generator(generatorTypes.scaleTuning, value / 128));\n }\n else\n // key to vol env hold\n if (source === DLSSources.keyNum && destination === DLSDestinations.volEnvHold)\n {\n applyKeyToCorrection(value, generatorTypes.keyNumToVolEnvHold, generatorTypes.holdVolEnv);\n }\n else\n // key to vol env decay\n if (source === DLSSources.keyNum && destination === DLSDestinations.volEnvDecay)\n {\n applyKeyToCorrection(value, generatorTypes.keyNumToVolEnvDecay, generatorTypes.decayVolEnv);\n }\n else\n // key to mod env hold\n if (source === DLSSources.keyNum && destination === DLSDestinations.modEnvHold)\n {\n applyKeyToCorrection(value, generatorTypes.keyNumToModEnvHold, generatorTypes.holdModEnv);\n }\n else\n // key to mod env decay\n if (source === DLSSources.keyNum && destination === DLSDestinations.modEnvDecay)\n {\n applyKeyToCorrection(value, generatorTypes.keyNumToModEnvDecay, generatorTypes.decayModEnv);\n }\n else\n {\n isGenerator = false;\n }\n \n }\n else\n {\n isGenerator = false;\n }\n if (isGenerator === false)\n {\n // UNCOMMENT TO ENABLE DEBUG\n // modulatorConverterDebug(source, control, destination, value, transform)\n // convert it to modulator\n const mod = getSF2ModulatorFromArticulator(\n source,\n control,\n destination,\n transform,\n value\n );\n if (mod)\n {\n // some articulators cannot be turned into modulators, that's why this check is a thing\n modulators.push(mod);\n SpessaSynthInfo(\"%cSucceeded converting to SF2 Modulator!\", consoleColors.recognized);\n }\n else\n {\n SpessaSynthWarn(\"Failed converting to SF2 Modulator!\");\n }\n }\n }\n }\n \n // it seems that dls 1 does not have vibrato lfo, so we shall disable it\n if (disableVibrato)\n {\n modulators.push(\n // mod to vib\n Modulator.copy(DLS_1_NO_VIBRATO_MOD),\n // press to vib\n Modulator.copy(DLS_1_NO_VIBRATO_PRESSURE)\n );\n }\n \n return { modulators: modulators, generators: generators };\n}", "import { readRIFFChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { readArticulation } from \"./read_articulation.js\";\n\n/**\n * @param lartChunk {RiffChunk|undefined}\n * @param lar2Chunk {RiffChunk|undefined}\n * @param zone {BasicInstrumentZone}\n * @this {DLSSoundFont}\n */\nexport function readLart(lartChunk, lar2Chunk, zone)\n{\n if (lartChunk)\n {\n while (lartChunk.chunkData.currentIndex < lartChunk.chunkData.length)\n {\n const art1 = readRIFFChunk(lartChunk.chunkData);\n this.verifyHeader(art1, \"art1\", \"art2\");\n const modsAndGens = readArticulation(art1, true);\n zone.generators.push(...modsAndGens.generators);\n zone.modulators.push(...modsAndGens.modulators);\n }\n }\n \n if (lar2Chunk)\n {\n while (lar2Chunk.chunkData.currentIndex < lar2Chunk.chunkData.length)\n {\n const art2 = readRIFFChunk(lar2Chunk.chunkData);\n this.verifyHeader(art2, \"art2\", \"art1\");\n const modsAndGens = readArticulation(art2, false);\n zone.generators.push(...modsAndGens.generators);\n zone.modulators.push(...modsAndGens.modulators);\n }\n }\n}", "import { BasicInstrumentZone } from \"../basic_soundfont/basic_zones.js\";\nimport { Generator, generatorTypes } from \"../basic_soundfont/generator.js\";\n\nexport class DLSZone extends BasicInstrumentZone\n{\n /**\n * @param keyRange {SoundFontRange}\n * @param velRange {SoundFontRange}\n */\n constructor(keyRange, velRange)\n {\n super();\n this.keyRange = keyRange;\n this.velRange = velRange;\n this.isGlobal = true;\n }\n \n /**\n * @param attenuationCb {number} with EMU correction\n * @param loopingMode {number} the sfont one\n * @param loop {{start: number, end: number}}\n * @param sampleKey {number}\n * @param sample {BasicSample}\n * @param sampleID {number}\n * @param samplePitchCorrection {number} cents\n */\n setWavesample(\n attenuationCb,\n loopingMode,\n loop,\n sampleKey,\n sample,\n sampleID,\n samplePitchCorrection\n )\n {\n if (loopingMode !== 0)\n {\n this.generators.push(new Generator(generatorTypes.sampleModes, loopingMode));\n }\n this.generators.push(new Generator(generatorTypes.initialAttenuation, attenuationCb));\n this.isGlobal = false;\n \n // correct tuning if needed\n samplePitchCorrection -= sample.samplePitchCorrection;\n const coarseTune = Math.trunc(samplePitchCorrection / 100);\n if (coarseTune !== 0)\n {\n this.generators.push(new Generator(generatorTypes.coarseTune, coarseTune));\n }\n const fineTune = samplePitchCorrection - (coarseTune * 100);\n if (fineTune !== 0)\n {\n this.generators.push(new Generator(generatorTypes.fineTune, fineTune));\n }\n \n // correct loop if needed\n if (loopingMode !== 0)\n {\n const diffStart = loop.start - sample.sampleLoopStartIndex;\n const diffEnd = loop.end - sample.sampleLoopEndIndex;\n if (diffStart !== 0)\n {\n const fine = diffStart % 32768;\n this.generators.push(new Generator(generatorTypes.startloopAddrsOffset, fine));\n // coarse generator uses 32768 samples per step\n const coarse = Math.trunc(diffStart / 32768);\n if (coarse !== 0)\n {\n this.generators.push(new Generator(generatorTypes.startloopAddrsCoarseOffset, coarse));\n }\n }\n if (diffEnd !== 0)\n {\n const fine = diffEnd % 32768;\n this.generators.push(new Generator(generatorTypes.endloopAddrsOffset, fine));\n // coarse generator uses 32768 samples per step\n const coarse = Math.trunc(diffEnd / 32768);\n if (coarse !== 0)\n {\n this.generators.push(new Generator(generatorTypes.endloopAddrsCoarseOffset, coarse));\n }\n }\n }\n // correct the key if needed\n if (sampleKey !== sample.samplePitch)\n {\n this.generators.push(new Generator(generatorTypes.overridingRootKey, sampleKey));\n }\n // add sample ID\n this.generators.push(new Generator(generatorTypes.sampleID, sampleID));\n this.sample = sample;\n sample.useCount++;\n }\n}", "import { readLittleEndian, signedInt16 } from \"../../utils/byte_functions/little_endian.js\";\nimport { findRIFFListType, readRIFFChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { DLSZone } from \"./dls_zone.js\";\nimport { Generator, generatorTypes } from \"../basic_soundfont/generator.js\";\n\n/**\n * @this {DLSSoundFont}\n * @param chunk {RiffChunk}\n * @returns {DLSZone}\n */\nexport function readRegion(chunk)\n{\n // regions are essentially instrument zones\n \n /**\n * read chunks in the region\n * @type {RiffChunk[]}\n */\n const regionChunks = [];\n while (chunk.chunkData.length > chunk.chunkData.currentIndex)\n {\n regionChunks.push(readRIFFChunk(chunk.chunkData));\n }\n \n // region header\n const regionHeader = regionChunks.find(c => c.header === \"rgnh\");\n // key range\n let keyMin = readLittleEndian(regionHeader.chunkData, 2);\n let keyMax = readLittleEndian(regionHeader.chunkData, 2);\n // vel range\n let velMin = readLittleEndian(regionHeader.chunkData, 2);\n let velMax = readLittleEndian(regionHeader.chunkData, 2);\n \n // a fix for not cool files\n if (velMin === 0 && velMax === 0)\n {\n velMax = 127;\n velMin = 0;\n }\n // cannot do the same to key zones sadly\n \n const zone = new DLSZone(\n { min: keyMin, max: keyMax },\n { min: velMin, max: velMax }\n );\n \n // fusOptions: no idea about that one???\n readLittleEndian(regionHeader.chunkData, 2);\n \n // keyGroup: essentially exclusive class\n const exclusive = readLittleEndian(regionHeader.chunkData, 2);\n if (exclusive !== 0)\n {\n zone.generators.push(new Generator(generatorTypes.exclusiveClass, exclusive));\n }\n \n // lart\n const lart = findRIFFListType(regionChunks, \"lart\");\n const lar2 = findRIFFListType(regionChunks, \"lar2\");\n this.readLart(lart, lar2, zone);\n \n // wsmp: wave sample chunk\n zone.isGlobal = false;\n const waveSampleChunk = regionChunks.find(c => c.header === \"wsmp\");\n // cbSize\n readLittleEndian(waveSampleChunk.chunkData, 4);\n let originalKey = readLittleEndian(waveSampleChunk.chunkData, 2);\n \n // sFineTune\n let pitchCorrection = signedInt16(\n waveSampleChunk.chunkData[waveSampleChunk.chunkData.currentIndex++],\n waveSampleChunk.chunkData[waveSampleChunk.chunkData.currentIndex++]\n );\n \n // gain correction: Each unit of gain represents 1/655360 dB\n // it is set after linking the sample\n const gainCorrection = readLittleEndian(waveSampleChunk.chunkData, 4);\n // convert to signed and turn into attenuation (invert)\n const dbCorrection = (gainCorrection | 0) / -655360;\n \n // skip options\n readLittleEndian(waveSampleChunk.chunkData, 4);\n \n // read loop count (always one or zero)\n const loopsAmount = readLittleEndian(waveSampleChunk.chunkData, 4);\n let loopingMode;\n const loop = { start: 0, end: 0 };\n if (loopsAmount === 0)\n {\n // no loop\n loopingMode = 0;\n }\n else\n {\n // ignore cbSize\n readLittleEndian(waveSampleChunk.chunkData, 4);\n // loop type: loop normally or loop until release (like soundfont)\n const loopType = readLittleEndian(waveSampleChunk.chunkData, 4); // why is it long?\n if (loopType === 0)\n {\n loopingMode = 1;\n }\n else\n {\n loopingMode = 3;\n }\n loop.start = readLittleEndian(waveSampleChunk.chunkData, 4);\n const loopLength = readLittleEndian(waveSampleChunk.chunkData, 4);\n loop.end = loop.start + loopLength;\n }\n \n // wave link\n const waveLinkChunk = regionChunks.find(c => c.header === \"wlnk\");\n if (waveLinkChunk === undefined)\n {\n // No wave link means no sample. What? Why is it even here then?\n return undefined;\n }\n \n // flags\n readLittleEndian(waveLinkChunk.chunkData, 2);\n // phase group\n readLittleEndian(waveLinkChunk.chunkData, 2);\n // channel\n readLittleEndian(waveLinkChunk.chunkData, 4);\n // sampleID\n const sampleID = readLittleEndian(waveLinkChunk.chunkData, 4);\n // noinspection JSValidateTypes\n /**\n * @type {DLSSample}\n */\n const sample = this.samples[sampleID];\n if (sample === undefined)\n {\n throw new Error(\"Invalid sample ID!\");\n }\n \n // this correction overrides the sample gain correction\n const actualDbCorrection = dbCorrection || sample.sampleDbAttenuation;\n // convert to centibels\n const attenuation = (actualDbCorrection * 10) / 0.4; // make sure to apply EMU correction\n \n zone.setWavesample(\n attenuation, loopingMode,\n loop,\n originalKey,\n sample,\n sampleID,\n pitchCorrection\n );\n return zone;\n}", "import { BasicSample } from \"../basic_soundfont/basic_sample.js\";\n\nexport class DLSSample extends BasicSample\n{\n /**\n * in decibels of attenuation, WITHOUT EMU CORRECTION\n * @type {number}\n */\n sampleDbAttenuation;\n /**\n * @type {Float32Array}\n */\n sampleData;\n \n /**\n * @param name {string}\n * @param rate {number}\n * @param pitch {number}\n * @param pitchCorrection {number}\n * @param loopStart {number} sample data points\n * @param loopEnd {number} sample data points\n * @param data {Float32Array}\n * @param sampleDbAttenuation {number} in db\n */\n constructor(\n name,\n rate,\n pitch,\n pitchCorrection,\n loopStart,\n loopEnd,\n data,\n sampleDbAttenuation\n )\n {\n super(\n name,\n rate,\n pitch,\n pitchCorrection,\n 0,\n 1,\n loopStart,\n loopEnd\n );\n this.sampleData = data;\n this.sampleDbAttenuation = sampleDbAttenuation;\n }\n \n getAudioData()\n {\n return this.sampleData;\n }\n \n getRawData()\n {\n if (this.isCompressed)\n {\n if (!this.compressedData)\n {\n throw new Error(\"Compressed but no data?? This shouldn't happen!!\");\n }\n return this.compressedData;\n }\n return super.getRawData();\n // const uint8 = new Uint8Array(this.sampleData.length * 2);\n // for (let i = 0; i < this.sampleData.length; i++)\n // {\n // const sample = Math.floor(this.sampleData[i] * 32768);\n // uint8[i * 2] = sample & 0xFF; // lower byte\n // uint8[i * 2 + 1] = (sample >> 8) & 0xFF; // upper byte\n // }\n // return uint8;\n }\n}", "import { findRIFFListType, readRIFFChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { readBytesAsString } from \"../../utils/byte_functions/string.js\";\nimport {\n SpessaSynthGroupCollapsed,\n SpessaSynthGroupEnd,\n SpessaSynthInfo,\n SpessaSynthWarn\n} from \"../../utils/loggin.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { readLittleEndian, signedInt16 } from \"../../utils/byte_functions/little_endian.js\";\nimport { DLSSample } from \"./dls_sample.js\";\n\nconst W_FORMAT_TAG = {\n PCM: 0x01,\n ALAW: 0x6\n};\n\n/**\n * @param dataChunk {RiffChunk}\n * @param bytesPerSample {number}\n * @returns {Float32Array}\n */\nfunction readPCM(dataChunk, bytesPerSample)\n{\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 {\n normalizationFactor = 255; // For 8-bit normalize from 0-255\n isUnsigned = true;\n }\n else\n {\n normalizationFactor = maxSampleValue; // For 16-bit normalize from -32,768 to 32,767\n }\n const sampleLength = dataChunk.size / bytesPerSample;\n const sampleData = new Float32Array(sampleLength);\n for (let i = 0; i < sampleData.length; i++)\n {\n // read\n let sample = readLittleEndian(dataChunk.chunkData, bytesPerSample);\n // turn into signed\n if (isUnsigned)\n {\n // normalize unsigned 8-bit sample\n sampleData[i] = (sample / normalizationFactor) - 0.5;\n }\n else\n {\n // normalize signed 16-bit sample\n if (sample >= maxSampleValue)\n {\n sample -= maxUnsigned;\n }\n sampleData[i] = sample / normalizationFactor;\n }\n }\n return sampleData;\n}\n\n/**\n * @param dataChunk {RiffChunk}\n * @param bytesPerSample {number}\n * @returns {Float32Array}\n */\nfunction readALAW(dataChunk, bytesPerSample)\n{\n const sampleLength = dataChunk.size / bytesPerSample;\n const sampleData = new Float32Array(sampleLength);\n for (let i = 0; i < sampleData.length; i++)\n {\n // read\n const input = readLittleEndian(dataChunk.chunkData, 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 let exponent = sample >> 4;\n // extract mantissa\n let mantissa = sample & 0xF;\n if (exponent > 0)\n {\n mantissa += 16; // add leading '1', if exponent > 0\n }\n \n mantissa = (mantissa << 4) + 0x8;\n if (exponent > 1)\n {\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\n/**\n * @this {DLSSoundFont}\n * @param waveListChunk {RiffChunk}\n */\nexport function readDLSSamples(waveListChunk)\n{\n SpessaSynthGroupCollapsed(\n \"%cLoading Wave samples...\",\n consoleColors.recognized\n );\n let sampleID = 0;\n while (waveListChunk.chunkData.currentIndex < waveListChunk.chunkData.length)\n {\n const waveChunk = readRIFFChunk(waveListChunk.chunkData);\n this.verifyHeader(waveChunk, \"LIST\");\n this.verifyText(readBytesAsString(waveChunk.chunkData, 4), \"wave\");\n \n /**\n * @type {RiffChunk[]}\n */\n const waveChunks = [];\n while (waveChunk.chunkData.currentIndex < waveChunk.chunkData.length)\n {\n waveChunks.push(readRIFFChunk(waveChunk.chunkData));\n }\n \n const fmtChunk = waveChunks.find(c => c.header === \"fmt \");\n if (!fmtChunk)\n {\n throw new Error(\"No fmt chunk in the wave file!\");\n }\n // https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.14393.0/shared/mmreg.h#L2108\n const waveFormat = readLittleEndian(fmtChunk.chunkData, 2);\n const channelsAmount = readLittleEndian(fmtChunk.chunkData, 2);\n if (channelsAmount !== 1)\n {\n throw new Error(`Only mono samples are supported. Fmt reports ${channelsAmount} channels`);\n }\n const sampleRate = readLittleEndian(fmtChunk.chunkData, 4);\n // skip avg bytes\n readLittleEndian(fmtChunk.chunkData, 4);\n // blockAlign\n readLittleEndian(fmtChunk.chunkData, 2);\n // it's bits per sample because one channel\n const wBitsPerSample = readLittleEndian(fmtChunk.chunkData, 2);\n const bytesPerSample = wBitsPerSample / 8;\n \n // read the data\n let failed = false;\n const dataChunk = waveChunks.find(c => c.header === \"data\");\n if (!dataChunk)\n {\n this.parsingError(\"No data chunk in the WAVE chunk!\");\n }\n let sampleData;\n switch (waveFormat)\n {\n default:\n failed = true;\n sampleData = new Float32Array(dataChunk.size / bytesPerSample);\n break;\n \n case W_FORMAT_TAG.PCM:\n sampleData = readPCM(dataChunk, bytesPerSample);\n break;\n \n case W_FORMAT_TAG.ALAW:\n sampleData = readALAW(dataChunk, bytesPerSample);\n break;\n \n }\n \n // read sample name\n const waveInfo = findRIFFListType(waveChunks, \"INFO\");\n let sampleName = `Unnamed ${sampleID}`;\n if (waveInfo)\n {\n let infoChunk = readRIFFChunk(waveInfo.chunkData);\n while (infoChunk.header !== \"INAM\" && waveInfo.chunkData.currentIndex < waveInfo.chunkData.length)\n {\n infoChunk = readRIFFChunk(waveInfo.chunkData);\n }\n if (infoChunk.header === \"INAM\")\n {\n sampleName = readBytesAsString(infoChunk.chunkData, infoChunk.size).trim();\n }\n }\n \n // correct defaults\n let sampleKey = 60;\n let samplePitch = 0;\n let sampleLoopStart = 0;\n let sampleLoopEnd = sampleData.length - 1;\n let sampleDbAttenuation = 0;\n \n // read wsmp\n const wsmpChunk = waveChunks.find(c => c.header === \"wsmp\");\n if (wsmpChunk)\n {\n // skip cbsize\n readLittleEndian(wsmpChunk.chunkData, 4);\n sampleKey = readLittleEndian(wsmpChunk.chunkData, 2);\n // section 1.14.2: Each relative pitch unit represents 1/65536 cents.\n // but that doesn't seem true for this one: it's just cents.\n samplePitch = signedInt16(\n wsmpChunk.chunkData[wsmpChunk.chunkData.currentIndex++],\n wsmpChunk.chunkData[wsmpChunk.chunkData.currentIndex++]\n );\n \n // pitch correction: convert hundreds to the root key\n const samplePitchSemitones = Math.trunc(samplePitch / 100);\n sampleKey += samplePitchSemitones;\n samplePitch -= samplePitchSemitones * 100;\n \n \n // gain is applied it manually here (literally multiplying the samples)\n const gainCorrection = readLittleEndian(wsmpChunk.chunkData, 4);\n // convert to signed and turn into decibels\n sampleDbAttenuation = (gainCorrection | 0) / -655360;\n // no idea about ful options\n readLittleEndian(wsmpChunk.chunkData, 4);\n const loopsAmount = readLittleEndian(wsmpChunk.chunkData, 4);\n if (loopsAmount === 1)\n {\n // skip size and type\n readLittleEndian(wsmpChunk.chunkData, 8);\n sampleLoopStart = readLittleEndian(wsmpChunk.chunkData, 4);\n const loopSize = readLittleEndian(wsmpChunk.chunkData, 4);\n sampleLoopEnd = sampleLoopStart + loopSize;\n }\n }\n else\n {\n SpessaSynthWarn(\"No wsmp chunk in wave... using sane defaults.\");\n }\n \n if (failed)\n {\n console.error(`Failed to load '${sampleName}': Unsupported format: (${waveFormat})`);\n }\n \n this.samples.push(new DLSSample(\n sampleName,\n sampleRate,\n sampleKey,\n samplePitch,\n sampleLoopStart,\n sampleLoopEnd,\n sampleData,\n sampleDbAttenuation\n ));\n \n \n sampleID++;\n SpessaSynthInfo(\n `%cLoaded sample %c${sampleName}`,\n consoleColors.info,\n consoleColors.recognized\n );\n }\n SpessaSynthGroupEnd();\n}", "import { BasicSoundBank } from \"../basic_soundfont/basic_soundfont.js\";\nimport { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../../utils/loggin.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { findRIFFListType, readRIFFChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { readBytesAsString } from \"../../utils/byte_functions/string.js\";\nimport { readLittleEndian } from \"../../utils/byte_functions/little_endian.js\";\nimport { readDLSInstrumentList } from \"./read_instrument_list.js\";\nimport { readDLSInstrument } from \"./read_instrument.js\";\nimport { readLart } from \"./read_lart.js\";\nimport { readRegion } from \"./read_region.js\";\nimport { readDLSSamples } from \"./read_samples.js\";\n\nclass DLSSoundFont extends BasicSoundBank\n{\n /**\n * Loads a new DLS (Downloadable sounds) soundfont\n * @param buffer {ArrayBuffer}\n */\n constructor(buffer)\n {\n super();\n this.dataArray = new IndexedByteArray(buffer);\n SpessaSynthGroup(\"%cParsing DLS...\", consoleColors.info);\n if (!this.dataArray)\n {\n SpessaSynthGroupEnd();\n this.parsingError(\"No data provided!\");\n }\n \n // read the main chunk\n let firstChunk = readRIFFChunk(this.dataArray, false);\n this.verifyHeader(firstChunk, \"riff\");\n this.verifyText(readBytesAsString(this.dataArray, 4).toLowerCase(), \"dls \");\n \n /**\n * Read the list\n * @type {RiffChunk[]}\n */\n const chunks = [];\n while (this.dataArray.currentIndex < this.dataArray.length)\n {\n chunks.push(readRIFFChunk(this.dataArray));\n }\n \n // mandatory\n this.soundFontInfo[\"ifil\"] = \"2.1\"; // always for dls\n this.soundFontInfo[\"isng\"] = \"EMU8000\";\n \n // set some defaults\n this.soundFontInfo[\"INAM\"] = \"Unnamed DLS\";\n this.soundFontInfo[\"IENG\"] = \"Unknown\";\n this.soundFontInfo[\"IPRD\"] = \"SpessaSynth DLS\";\n this.soundFontInfo[\"ICRD\"] = new Date().toDateString();\n \n // read info\n const infoChunk = findRIFFListType(chunks, \"INFO\");\n if (infoChunk)\n {\n while (infoChunk.chunkData.currentIndex < infoChunk.chunkData.length)\n {\n const infoPart = readRIFFChunk(infoChunk.chunkData);\n this.soundFontInfo[infoPart.header] = readBytesAsString(infoPart.chunkData, infoPart.size);\n }\n }\n this.soundFontInfo[\"ICMT\"] = this.soundFontInfo[\"ICMT\"] || \"(No description)\";\n if (this.soundFontInfo[\"ISBJ\"])\n {\n // merge it\n this.soundFontInfo[\"ICMT\"] += \"\\n\" + this.soundFontInfo[\"ISBJ\"];\n delete this.soundFontInfo[\"ISBJ\"];\n }\n this.soundFontInfo[\"ICMT\"] += \"\\nConverted from DLS to SF2 with SpessaSynth\";\n \n for (const [info, value] of Object.entries(this.soundFontInfo))\n {\n SpessaSynthInfo(\n `%c\"${info}\": %c\"${value}\"`,\n consoleColors.info,\n consoleColors.recognized\n );\n }\n \n // read \"colh\"\n let colhChunk = chunks.find(c => c.header === \"colh\");\n if (!colhChunk)\n {\n SpessaSynthGroupEnd();\n this.parsingError(\"No colh chunk!\");\n }\n this.instrumentAmount = readLittleEndian(colhChunk.chunkData, 4);\n SpessaSynthInfo(\n `%cInstruments amount: %c${this.instrumentAmount}`,\n consoleColors.info,\n consoleColors.recognized\n );\n \n // read the wave list\n let waveListChunk = findRIFFListType(chunks, \"wvpl\");\n if (!waveListChunk)\n {\n SpessaSynthGroupEnd();\n this.parsingError(\"No wvpl chunk!\");\n }\n this.readDLSSamples(waveListChunk);\n \n // read the instrument list\n let instrumentListChunk = findRIFFListType(chunks, \"lins\");\n if (!instrumentListChunk)\n {\n SpessaSynthGroupEnd();\n this.parsingError(\"No lins chunk!\");\n }\n this.readDLSInstrumentList(instrumentListChunk);\n \n // sort presets\n this.presets.sort((a, b) => (a.program - b.program) + (a.bank - b.bank));\n this._parseInternal();\n SpessaSynthInfo(\n `%cParsing finished! %c\"${this.soundFontInfo[\"INAM\"] || \"UNNAMED\"}\"%c has %c${this.presets.length} %cpresets,\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 /**\n * @param chunk {RiffChunk}\n * @param expected {string}\n */\n verifyHeader(chunk, ...expected)\n {\n for (const expect of expected)\n {\n if (chunk.header.toLowerCase() === expect.toLowerCase())\n {\n return;\n }\n }\n SpessaSynthGroupEnd();\n this.parsingError(`Invalid DLS chunk header! Expected \"${expected.toString()}\" got \"${chunk.header.toLowerCase()}\"`);\n }\n \n /**\n * @param text {string}\n * @param expected {string}\n */\n verifyText(text, expected)\n {\n if (text.toLowerCase() !== expected.toLowerCase())\n {\n SpessaSynthGroupEnd();\n this.parsingError(`FourCC error: Expected \"${expected.toLowerCase()}\" got \"${text.toLowerCase()}\"`);\n }\n }\n \n /**\n * @param error {string}\n */\n parsingError(error)\n {\n throw new Error(`DLS parse error: ${error} The file may be corrupted.`);\n }\n \n destroySoundBank()\n {\n super.destroySoundBank();\n delete this.dataArray;\n }\n}\n\nDLSSoundFont.prototype.readDLSInstrumentList = readDLSInstrumentList;\nDLSSoundFont.prototype.readDLSInstrument = readDLSInstrument;\nDLSSoundFont.prototype.readRegion = readRegion;\nDLSSoundFont.prototype.readLart = readLart;\nDLSSoundFont.prototype.readDLSSamples = readDLSSamples;\n\nexport { DLSSoundFont };", "import { RiffChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { readLittleEndian, signedInt8 } from \"../../utils/byte_functions/little_endian.js\";\nimport { stbvorbis } from \"../../externals/stbvorbis_sync/stbvorbis_sync.min.js\";\nimport { SpessaSynthWarn } from \"../../utils/loggin.js\";\nimport { readBytesAsString } from \"../../utils/byte_functions/string.js\";\nimport { BasicSample } from \"../basic_soundfont/basic_sample.js\";\n\nexport class SoundFontSample extends BasicSample\n{\n /**\n * Creates a sample\n * @param sampleName {string}\n * @param sampleStartIndex {number}\n * @param sampleEndIndex {number}\n * @param sampleLoopStartIndex {number}\n * @param sampleLoopEndIndex {number}\n * @param sampleRate {number}\n * @param samplePitch {number}\n * @param samplePitchCorrection {number}\n * @param sampleLink {number}\n * @param sampleType {number}\n * @param smplArr {IndexedByteArray|Float32Array}\n * @param sampleIndex {number} initial sample index when loading the sfont\n * @param isDataRaw {boolean} if false, the data is decoded as float32.\n * Used for SF2Pack support\n */\n constructor(\n sampleName,\n sampleStartIndex,\n sampleEndIndex,\n sampleLoopStartIndex,\n sampleLoopEndIndex,\n sampleRate,\n samplePitch,\n samplePitchCorrection,\n sampleLink,\n sampleType,\n smplArr,\n sampleIndex,\n isDataRaw\n )\n {\n super(\n sampleName,\n sampleRate,\n samplePitch,\n samplePitchCorrection,\n sampleLink,\n sampleType,\n sampleLoopStartIndex - (sampleStartIndex / 2),\n sampleLoopEndIndex - (sampleStartIndex / 2)\n );\n this.sampleName = sampleName;\n // in bytes\n this.sampleStartIndex = sampleStartIndex;\n this.sampleEndIndex = sampleEndIndex;\n this.isSampleLoaded = false;\n this.sampleID = sampleIndex;\n // in bytes\n this.sampleLength = this.sampleEndIndex - this.sampleStartIndex;\n this.sampleDataArray = smplArr;\n this.sampleData = new Float32Array(0);\n if (this.isCompressed)\n {\n // correct loop points\n this.sampleLoopStartIndex += this.sampleStartIndex / 2;\n this.sampleLoopEndIndex += this.sampleStartIndex / 2;\n this.sampleLength = 99999999; // set to 999,999 before we decode it\n }\n this.isDataRaw = isDataRaw;\n }\n \n /**\n * Get raw data, whether it's compressed or not as we simply write it to the file\n * @return {Uint8Array} either s16 or vorbis data\n */\n getRawData()\n {\n const smplArr = this.sampleDataArray;\n if (this.isCompressed)\n {\n if (this.compressedData)\n {\n return this.compressedData;\n }\n const smplStart = smplArr.currentIndex;\n return smplArr.slice(this.sampleStartIndex / 2 + smplStart, this.sampleEndIndex / 2 + smplStart);\n }\n else\n {\n if (!this.isDataRaw)\n {\n // encode the f32 into s16 manually\n super.getRawData();\n }\n const dataStartIndex = smplArr.currentIndex;\n return smplArr.slice(dataStartIndex + this.sampleStartIndex, dataStartIndex + this.sampleEndIndex);\n }\n }\n \n /**\n * Decode binary vorbis into a float32 pcm\n */\n decodeVorbis()\n {\n if (this.sampleLength < 1)\n {\n // eos, do not do anything\n return;\n }\n // get the compressed byte stream\n const smplArr = this.sampleDataArray;\n const smplStart = smplArr.currentIndex;\n const buff = smplArr.slice(this.sampleStartIndex / 2 + smplStart, this.sampleEndIndex / 2 + smplStart);\n // reset array and being decoding\n this.sampleData = new Float32Array(0);\n try\n {\n /**\n * @type {{data: Float32Array[], error: (string|null), sampleRate: number, eof: boolean}}\n */\n const vorbis = stbvorbis.decode(buff.buffer);\n this.sampleData = vorbis.data[0];\n if (this.sampleData === undefined)\n {\n SpessaSynthWarn(`Error decoding sample ${this.sampleName}: Vorbis decode returned undefined.`);\n }\n }\n catch (e)\n {\n // do not error out, fill with silence\n SpessaSynthWarn(`Error decoding sample ${this.sampleName}: ${e}`);\n this.sampleData = new Float32Array(this.sampleLoopEndIndex + 1);\n }\n }\n \n /**\n * Loads the audio data and stores it for reuse\n * @returns {Float32Array} The audioData\n */\n getAudioData()\n {\n if (!this.isSampleLoaded)\n {\n // start loading data if it is not loaded\n if (this.sampleLength < 1)\n {\n SpessaSynthWarn(`Invalid sample ${this.sampleName}! Invalid length: ${this.sampleLength}`);\n return new Float32Array(1);\n }\n \n if (this.isCompressed)\n {\n // if compressed, decode\n this.decodeVorbis();\n this.isSampleLoaded = true;\n return this.sampleData;\n }\n else if (!this.isDataRaw)\n {\n return this.getUncompressedReadyData();\n }\n return this.loadUncompressedData();\n }\n return this.sampleData;\n }\n \n /**\n * @returns {Float32Array}\n */\n loadUncompressedData()\n {\n if (this.isCompressed)\n {\n SpessaSynthWarn(\"Trying to load a compressed sample via loadUncompressedData()... aborting!\");\n return new Float32Array(0);\n }\n \n // read the sample data\n let audioData = new Float32Array(this.sampleLength / 2);\n const dataStartIndex = this.sampleDataArray.currentIndex;\n let convertedSigned16 = new Int16Array(\n this.sampleDataArray.slice(dataStartIndex + this.sampleStartIndex, dataStartIndex + this.sampleEndIndex)\n .buffer\n );\n \n // convert to float\n for (let i = 0; i < convertedSigned16.length; i++)\n {\n audioData[i] = convertedSigned16[i] / 32768;\n }\n \n this.sampleData = audioData;\n this.isSampleLoaded = true;\n return audioData;\n }\n \n /**\n * @returns {Float32Array}\n */\n getUncompressedReadyData()\n {\n /**\n * read the sample data\n * @type {Float32Array}\n */\n let audioData = this.sampleDataArray.slice(this.sampleStartIndex / 2, this.sampleEndIndex / 2);\n this.sampleData = audioData;\n this.isSampleLoaded = true;\n return audioData;\n }\n}\n\n/**\n * Reads the generatorTranslator from the shdr read\n * @param sampleHeadersChunk {RiffChunk}\n * @param smplChunkData {IndexedByteArray|Float32Array}\n * @param isSmplDataRaw {boolean}\n * @returns {SoundFontSample[]}\n */\nexport function readSamples(sampleHeadersChunk, smplChunkData, isSmplDataRaw = true)\n{\n /**\n * @type {SoundFontSample[]}\n */\n let samples = [];\n let index = 0;\n while (sampleHeadersChunk.chunkData.length > sampleHeadersChunk.chunkData.currentIndex)\n {\n const sample = readSample(index, sampleHeadersChunk.chunkData, smplChunkData, isSmplDataRaw);\n samples.push(sample);\n index++;\n }\n // remove EOS\n if (samples.length > 1)\n {\n samples.pop();\n }\n return samples;\n}\n\n/**\n * Reads it into a sample\n * @param index {number}\n * @param sampleHeaderData {IndexedByteArray}\n * @param smplArrayData {IndexedByteArray|Float32Array}\n * @param isDataRaw {boolean} true means binary 16-bit data, false means float32\n * @returns {SoundFontSample}\n */\nfunction readSample(index, sampleHeaderData, smplArrayData, isDataRaw)\n{\n \n // read the sample name\n let sampleName = readBytesAsString(sampleHeaderData, 20);\n \n // read the sample start index\n let sampleStartIndex = readLittleEndian(sampleHeaderData, 4) * 2;\n \n // read the sample end index\n let sampleEndIndex = readLittleEndian(sampleHeaderData, 4) * 2;\n \n // read the sample looping start index\n let sampleLoopStartIndex = readLittleEndian(sampleHeaderData, 4);\n \n // read the sample looping end index\n let sampleLoopEndIndex = readLittleEndian(sampleHeaderData, 4);\n \n // read the sample rate\n let sampleRate = readLittleEndian(sampleHeaderData, 4);\n \n // read the original sample pitch\n let samplePitch = sampleHeaderData[sampleHeaderData.currentIndex++];\n if (samplePitch === 255)\n {\n // if it's 255, then default to 60\n samplePitch = 60;\n }\n \n // read the sample pitch correction\n let samplePitchCorrection = signedInt8(sampleHeaderData[sampleHeaderData.currentIndex++]);\n \n \n // read the link to the other channel\n let sampleLink = readLittleEndian(sampleHeaderData, 2);\n let sampleType = readLittleEndian(sampleHeaderData, 2);\n \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 isDataRaw\n );\n}", "import { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { RiffChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { signedInt16 } from \"../../utils/byte_functions/little_endian.js\";\nimport { Generator } from \"../basic_soundfont/generator.js\";\n\n\nexport class ReadGenerator extends Generator\n{\n /**\n * Creates a generator\n * @param dataArray {IndexedByteArray}\n */\n constructor(dataArray)\n {\n super();\n // 4 bytes:\n // type, type, type, value\n const i = dataArray.currentIndex;\n /**\n * @type {generatorTypes|number}\n */\n this.generatorType = (dataArray[i + 1] << 8) | dataArray[i];\n this.generatorValue = signedInt16(dataArray[i + 2], dataArray[i + 3]);\n dataArray.currentIndex += 4;\n }\n}\n\n/**\n * Reads the generator read\n * @param generatorChunk {RiffChunk}\n * @returns {Generator[]}\n */\nexport function readGenerators(generatorChunk)\n{\n let gens = [];\n while (generatorChunk.chunkData.length > generatorChunk.chunkData.currentIndex)\n {\n gens.push(new ReadGenerator(generatorChunk.chunkData));\n }\n if (gens.length > 1)\n {\n // remove terminal\n gens.pop();\n }\n return gens;\n}", "import { readLittleEndian } from \"../../utils/byte_functions/little_endian.js\";\nimport { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { RiffChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { BasicInstrumentZone, BasicPresetZone } from \"../basic_soundfont/basic_zones.js\";\nimport { Generator, generatorTypes } from \"../basic_soundfont/generator.js\";\nimport { Modulator } from \"../basic_soundfont/modulator.js\";\n\n/**\n * zones.js\n * purpose: reads instrumend and preset zones from soundfont and gets their respective samples and generators and modulators\n */\n\nexport class InstrumentZone extends BasicInstrumentZone\n{\n /**\n * Creates a zone (instrument)\n * @param dataArray {IndexedByteArray}\n */\n constructor(dataArray)\n {\n super();\n this.generatorZoneStartIndex = readLittleEndian(dataArray, 2);\n this.modulatorZoneStartIndex = readLittleEndian(dataArray, 2);\n this.modulatorZoneSize = 0;\n this.generatorZoneSize = 0;\n this.isGlobal = true;\n }\n \n setZoneSize(modulatorZoneSize, generatorZoneSize)\n {\n this.modulatorZoneSize = modulatorZoneSize;\n this.generatorZoneSize = generatorZoneSize;\n }\n \n /**\n * grab the generators\n * @param generators {Generator[]}\n */\n getGenerators(generators)\n {\n for (let i = this.generatorZoneStartIndex; i < this.generatorZoneStartIndex + this.generatorZoneSize; i++)\n {\n this.generators.push(generators[i]);\n }\n }\n \n /**\n * grab the modulators\n * @param modulators {Modulator[]}\n */\n getModulators(modulators)\n {\n for (let i = this.modulatorZoneStartIndex; i < this.modulatorZoneStartIndex + this.modulatorZoneSize; i++)\n {\n this.modulators.push(modulators[i]);\n }\n }\n \n /**\n * Loads the zone's sample\n * @param samples {BasicSample[]}\n */\n getSample(samples)\n {\n let sampleID = this.generators.find(g => g.generatorType === generatorTypes.sampleID);\n if (sampleID)\n {\n this.sample = samples[sampleID.generatorValue];\n this.isGlobal = false;\n this.sample.useCount++;\n }\n }\n \n /**\n * Reads the keyRange of the zone\n */\n getKeyRange()\n {\n let range = this.generators.find(g => g.generatorType === generatorTypes.keyRange);\n if (range)\n {\n this.keyRange.min = range.generatorValue & 0x7F;\n this.keyRange.max = (range.generatorValue >> 8) & 0x7F;\n }\n }\n \n /**\n * reads the velolicty range of the zone\n */\n getVelRange()\n {\n let range = this.generators.find(g => g.generatorType === generatorTypes.velRange);\n if (range)\n {\n this.velRange.min = range.generatorValue & 0x7F;\n this.velRange.max = (range.generatorValue >> 8) & 0x7F;\n }\n }\n}\n\n/**\n * Reads the given instrument zone read\n * @param zonesChunk {RiffChunk}\n * @param instrumentGenerators {Generator[]}\n * @param instrumentModulators {Modulator[]}\n * @param instrumentSamples {BasicSample[]}\n * @returns {InstrumentZone[]}\n */\nexport function readInstrumentZones(zonesChunk, instrumentGenerators, instrumentModulators, instrumentSamples)\n{\n /**\n * @type {InstrumentZone[]}\n */\n let zones = [];\n while (zonesChunk.chunkData.length > zonesChunk.chunkData.currentIndex)\n {\n let zone = new InstrumentZone(zonesChunk.chunkData);\n if (zones.length > 0)\n {\n let modulatorZoneSize = zone.modulatorZoneStartIndex - zones[zones.length - 1].modulatorZoneStartIndex;\n let generatorZoneSize = zone.generatorZoneStartIndex - zones[zones.length - 1].generatorZoneStartIndex;\n zones[zones.length - 1].setZoneSize(modulatorZoneSize, generatorZoneSize);\n zones[zones.length - 1].getGenerators(instrumentGenerators);\n zones[zones.length - 1].getModulators(instrumentModulators);\n zones[zones.length - 1].getSample(instrumentSamples);\n zones[zones.length - 1].getKeyRange();\n zones[zones.length - 1].getVelRange();\n }\n zones.push(zone);\n }\n if (zones.length > 1)\n {\n // remove terminal\n zones.pop();\n }\n return zones;\n}\n\nexport class PresetZone extends BasicPresetZone\n{\n /**\n * Creates a zone (preset)\n * @param dataArray {IndexedByteArray}\n */\n constructor(dataArray)\n {\n super();\n this.generatorZoneStartIndex = readLittleEndian(dataArray, 2);\n this.modulatorZoneStartIndex = readLittleEndian(dataArray, 2);\n this.modulatorZoneSize = 0;\n this.generatorZoneSize = 0;\n this.isGlobal = true;\n }\n \n setZoneSize(modulatorZoneSize, generatorZoneSize)\n {\n this.modulatorZoneSize = modulatorZoneSize;\n this.generatorZoneSize = generatorZoneSize;\n }\n \n /**\n * grab the generators\n * @param generators {Generator[]}\n */\n getGenerators(generators)\n {\n for (let i = this.generatorZoneStartIndex; i < this.generatorZoneStartIndex + this.generatorZoneSize; i++)\n {\n this.generators.push(generators[i]);\n }\n }\n \n /**\n * grab the modulators\n * @param modulators {Modulator[]}\n */\n getModulators(modulators)\n {\n for (let i = this.modulatorZoneStartIndex; i < this.modulatorZoneStartIndex + this.modulatorZoneSize; i++)\n {\n this.modulators.push(modulators[i]);\n }\n }\n \n /**\n * grab the instrument\n * @param instruments {BasicInstrument[]}\n */\n getInstrument(instruments)\n {\n let instrumentID = this.generators.find(g => g.generatorType === generatorTypes.instrument);\n if (instrumentID)\n {\n this.instrument = instruments[instrumentID.generatorValue];\n this.instrument.addUseCount();\n this.isGlobal = false;\n }\n }\n \n /**\n * Reads the keyRange of the zone\n */\n getKeyRange()\n {\n let range = this.generators.find(g => g.generatorType === generatorTypes.keyRange);\n if (range)\n {\n this.keyRange.min = range.generatorValue & 0x7F;\n this.keyRange.max = (range.generatorValue >> 8) & 0x7F;\n }\n }\n \n /**\n * reads the velolicty range of the zone\n */\n getVelRange()\n {\n let range = this.generators.find(g => g.generatorType === generatorTypes.velRange);\n if (range)\n {\n this.velRange.min = range.generatorValue & 0x7F;\n this.velRange.max = (range.generatorValue >> 8) & 0x7F;\n }\n }\n}\n\n/**\n * Reads the given preset zone read\n * @param zonesChunk {RiffChunk}\n * @param presetGenerators {Generator[]}\n * @param instruments {BasicInstrument[]}\n * @param presetModulators {Modulator[]}\n * @returns {PresetZone[]}\n */\nexport function readPresetZones(zonesChunk, presetGenerators, presetModulators, instruments)\n{\n /**\n * @type {PresetZone[]}\n */\n let zones = [];\n while (zonesChunk.chunkData.length > zonesChunk.chunkData.currentIndex)\n {\n let zone = new PresetZone(zonesChunk.chunkData);\n if (zones.length > 0)\n {\n let modulatorZoneSize = zone.modulatorZoneStartIndex - zones[zones.length - 1].modulatorZoneStartIndex;\n let generatorZoneSize = zone.generatorZoneStartIndex - zones[zones.length - 1].generatorZoneStartIndex;\n zones[zones.length - 1].setZoneSize(modulatorZoneSize, generatorZoneSize);\n zones[zones.length - 1].getGenerators(presetGenerators);\n zones[zones.length - 1].getModulators(presetModulators);\n zones[zones.length - 1].getInstrument(instruments);\n zones[zones.length - 1].getKeyRange();\n zones[zones.length - 1].getVelRange();\n }\n zones.push(zone);\n }\n if (zones.length > 1)\n {\n // remove terminal\n zones.pop();\n }\n return zones;\n}", "import { RiffChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { PresetZone } from \"./zones.js\";\nimport { readLittleEndian } from \"../../utils/byte_functions/little_endian.js\";\nimport { readBytesAsString } from \"../../utils/byte_functions/string.js\";\nimport { BasicPreset } from \"../basic_soundfont/basic_preset.js\";\n\n/**\n * parses soundfont presets, also includes function for getting the generators and samples from midi note and velocity\n */\n\nexport class Preset extends BasicPreset\n{\n /**\n * Creates a preset\n * @param presetChunk {RiffChunk}\n * @param sf2 {BasicSoundBank}\n */\n constructor(presetChunk, sf2)\n {\n super(sf2);\n this.presetName = readBytesAsString(presetChunk.chunkData, 20)\n .trim()\n .replace(/\\d{3}:\\d{3}/, \"\"); // remove those pesky \"000:001\"\n \n this.program = readLittleEndian(presetChunk.chunkData, 2);\n this.bank = readLittleEndian(presetChunk.chunkData, 2);\n this.presetZoneStartIndex = readLittleEndian(presetChunk.chunkData, 2);\n \n // read the dword\n this.library = readLittleEndian(presetChunk.chunkData, 4);\n this.genre = readLittleEndian(presetChunk.chunkData, 4);\n this.morphology = readLittleEndian(presetChunk.chunkData, 4);\n this.presetZonesAmount = 0;\n }\n \n /**\n * Loads all the preset zones, given the amount\n * @param amount {number}\n * @param zones {PresetZone[]}\n */\n getPresetZones(amount, zones)\n {\n this.presetZonesAmount = amount;\n for (let i = this.presetZoneStartIndex; i < this.presetZonesAmount + this.presetZoneStartIndex; i++)\n {\n this.presetZones.push(zones[i]);\n }\n }\n}\n\n/**\n * Reads the presets\n * @param presetChunk {RiffChunk}\n * @param presetZones {PresetZone[]}\n * @param sf2 {BasicSoundBank}\n * @returns {Preset[]}\n */\nexport function readPresets(presetChunk, presetZones, sf2)\n{\n /**\n * @type {Preset[]}\n */\n let presets = [];\n while (presetChunk.chunkData.length > presetChunk.chunkData.currentIndex)\n {\n let preset = new Preset(presetChunk, sf2);\n if (presets.length > 0)\n {\n let presetZonesAmount = preset.presetZoneStartIndex - presets[presets.length - 1].presetZoneStartIndex;\n presets[presets.length - 1].getPresetZones(presetZonesAmount, presetZones);\n }\n presets.push(preset);\n }\n // remove EOP\n if (presets.length > 1)\n {\n presets.pop();\n }\n return presets;\n}", "import { RiffChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { InstrumentZone } from \"./zones.js\";\nimport { readLittleEndian } from \"../../utils/byte_functions/little_endian.js\";\nimport { readBytesAsString } from \"../../utils/byte_functions/string.js\";\nimport { BasicInstrument } from \"../basic_soundfont/basic_instrument.js\";\n\n/**\n * instrument.js\n * purpose: parses soundfont instrument and stores them as a class\n */\n\nexport class Instrument extends BasicInstrument\n{\n /**\n * Creates an instrument\n * @param instrumentChunk {RiffChunk}\n */\n constructor(instrumentChunk)\n {\n super();\n this.instrumentName = readBytesAsString(instrumentChunk.chunkData, 20).trim();\n this.instrumentZoneIndex = readLittleEndian(instrumentChunk.chunkData, 2);\n this.instrumentZonesAmount = 0;\n }\n \n /**\n * Loads all the instrument zones, given the amount\n * @param amount {number}\n * @param zones {InstrumentZone[]}\n */\n getInstrumentZones(amount, zones)\n {\n this.instrumentZonesAmount = amount;\n for (let i = this.instrumentZoneIndex; i < this.instrumentZonesAmount + this.instrumentZoneIndex; i++)\n {\n this.instrumentZones.push(zones[i]);\n }\n }\n}\n\n/**\n * Reads the instruments\n * @param instrumentChunk {RiffChunk}\n * @param instrumentZones {InstrumentZone[]}\n * @returns {Instrument[]}\n */\nexport function readInstruments(instrumentChunk, instrumentZones)\n{\n let instruments = [];\n while (instrumentChunk.chunkData.length > instrumentChunk.chunkData.currentIndex)\n {\n let instrument = new Instrument(instrumentChunk);\n if (instruments.length > 0)\n {\n let instrumentsAmount = instrument.instrumentZoneIndex - instruments[instruments.length - 1].instrumentZoneIndex;\n instruments[instruments.length - 1].getInstrumentZones(instrumentsAmount, instrumentZones);\n }\n instruments.push(instrument);\n }\n if (instruments.length > 1)\n {\n // remove EOI\n instruments.pop();\n }\n return instruments;\n}", "import { readLittleEndian, signedInt16 } from \"../../utils/byte_functions/little_endian.js\";\nimport { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { Modulator } from \"../basic_soundfont/modulator.js\";\n\n\nexport class ReadModulator extends Modulator\n{\n /**\n * Creates a modulator\n * @param dataArray {IndexedByteArray}\n */\n constructor(dataArray)\n {\n const srcEnum = readLittleEndian(dataArray, 2);\n const destination = readLittleEndian(dataArray, 2);\n const amount = signedInt16(dataArray[dataArray.currentIndex++], dataArray[dataArray.currentIndex++]);\n const secSrcEnum = readLittleEndian(dataArray, 2);\n const transformType = readLittleEndian(dataArray, 2);\n super(srcEnum, secSrcEnum, destination, amount, transformType);\n }\n}\n\n/**\n * Reads the modulator read\n * @param modulatorChunk {RiffChunk}\n * @returns {Modulator[]}\n */\nexport function readModulators(modulatorChunk)\n{\n let gens = [];\n while (modulatorChunk.chunkData.length > modulatorChunk.chunkData.currentIndex)\n {\n gens.push(new ReadModulator(modulatorChunk.chunkData));\n }\n return gens;\n}", "import { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { readSamples } from \"./samples.js\";\nimport { readLittleEndian } from \"../../utils/byte_functions/little_endian.js\";\nimport { readGenerators } from \"./generators.js\";\nimport { InstrumentZone, readInstrumentZones, readPresetZones } from \"./zones.js\";\nimport { readPresets } from \"./presets.js\";\nimport { readInstruments } from \"./instruments.js\";\nimport { readModulators } from \"./modulators.js\";\nimport { readRIFFChunk, RiffChunk } from \"../basic_soundfont/riff_chunk.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../../utils/loggin.js\";\nimport { readBytesAsString } from \"../../utils/byte_functions/string.js\";\nimport { stbvorbis } from \"../../externals/stbvorbis_sync/stbvorbis_sync.min.js\";\nimport { BasicSoundBank } from \"../basic_soundfont/basic_soundfont.js\";\nimport { Generator } from \"../basic_soundfont/generator.js\";\nimport { Modulator } from \"../basic_soundfont/modulator.js\";\n\n/**\n * soundfont.js\n * purpose: parses a soundfont2 file\n */\n\nexport class SoundFont2 extends BasicSoundBank\n{\n /**\n * Initializes a new SoundFont2 Parser and parses the given data array\n * @param arrayBuffer {ArrayBuffer}\n * @param warnDeprecated {boolean}\n */\n constructor(arrayBuffer, warnDeprecated = true)\n {\n super();\n if (warnDeprecated)\n {\n console.warn(\"Using the constructor directly is deprecated. Use loadSoundFont instead.\");\n }\n this.dataArray = new IndexedByteArray(arrayBuffer);\n SpessaSynthGroup(\"%cParsing SoundFont...\", consoleColors.info);\n if (!this.dataArray)\n {\n SpessaSynthGroupEnd();\n this.parsingError(\"No data provided!\");\n }\n \n // read the main read\n let firstChunk = readRIFFChunk(this.dataArray, false);\n this.verifyHeader(firstChunk, \"riff\");\n \n const type = readBytesAsString(this.dataArray, 4).toLowerCase();\n if (type !== \"sfbk\" && type !== \"sfpk\")\n {\n SpessaSynthGroupEnd();\n throw new SyntaxError(`Invalid soundFont! Expected \"sfbk\" or \"sfpk\" got \"${type}\"`);\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 let infoChunk = readRIFFChunk(this.dataArray);\n this.verifyHeader(infoChunk, \"list\");\n readBytesAsString(infoChunk.chunkData, 4);\n \n while (infoChunk.chunkData.length > infoChunk.chunkData.currentIndex)\n {\n let chunk = readRIFFChunk(infoChunk.chunkData);\n let text;\n // special cases\n switch (chunk.header.toLowerCase())\n {\n case \"ifil\":\n case \"iver\":\n text = `${readLittleEndian(chunk.chunkData, 2)}.${readLittleEndian(chunk.chunkData, 2)}`;\n this.soundFontInfo[chunk.header] = text;\n break;\n \n case \"icmt\":\n text = readBytesAsString(chunk.chunkData, chunk.chunkData.length, undefined, false);\n this.soundFontInfo[chunk.header] = text;\n break;\n \n // dmod: default modulators\n case \"dmod\":\n const newModulators = readModulators(chunk);\n newModulators.pop(); // remove the terminal record\n text = `Modulators: ${newModulators.length}`;\n // override default modulators\n const oldDefaults = this.defaultModulators;\n \n this.defaultModulators = newModulators;\n this.defaultModulators.push(...oldDefaults.filter(m => !this.defaultModulators.find(mm => Modulator.isIdentical(\n m,\n mm\n ))));\n this.soundFontInfo[chunk.header] = chunk.chunkData;\n break;\n \n default:\n text = readBytesAsString(chunk.chunkData, chunk.chunkData.length);\n this.soundFontInfo[chunk.header] = text;\n }\n \n SpessaSynthInfo(\n `%c\"${chunk.header}\": %c\"${text}\"`,\n consoleColors.info,\n consoleColors.recognized\n );\n }\n \n // SDTA\n const sdtaChunk = readRIFFChunk(this.dataArray, false);\n this.verifyHeader(sdtaChunk, \"list\");\n this.verifyText(readBytesAsString(this.dataArray, 4), \"sdta\");\n \n // smpl\n SpessaSynthInfo(\"%cVerifying smpl chunk...\", consoleColors.warn);\n let sampleDataChunk = readRIFFChunk(this.dataArray, false);\n this.verifyHeader(sampleDataChunk, \"smpl\");\n /**\n * @type {IndexedByteArray|Float32Array}\n */\n let sampleData;\n // SF2Pack: the entire data is compressed\n if (isSF2Pack)\n {\n SpessaSynthInfo(\n \"%cSF2Pack detected, attempting to decode the smpl chunk...\",\n consoleColors.info\n );\n try\n {\n /**\n * @type {Float32Array}\n */\n sampleData = stbvorbis.decode(this.dataArray.buffer.slice(\n this.dataArray.currentIndex,\n this.dataArray.currentIndex + sdtaChunk.size - 12\n )).data[0];\n }\n catch (e)\n {\n SpessaSynthGroupEnd();\n throw new Error(`SF2Pack Ogg Vorbis decode error: ${e}`);\n }\n SpessaSynthInfo(\n `%cDecoded the smpl chunk! Length: %c${sampleData.length}`,\n consoleColors.info,\n consoleColors.value\n );\n }\n else\n {\n /**\n * @type {IndexedByteArray}\n */\n sampleData = this.dataArray;\n this.sampleDataStartIndex = this.dataArray.currentIndex;\n }\n \n SpessaSynthInfo(\n `%cSkipping sample chunk, length: %c${sdtaChunk.size - 12}`,\n consoleColors.info,\n consoleColors.value\n );\n this.dataArray.currentIndex += sdtaChunk.size - 12;\n \n // PDTA\n SpessaSynthInfo(\"%cLoading preset data chunk...\", consoleColors.warn);\n let presetChunk = readRIFFChunk(this.dataArray);\n this.verifyHeader(presetChunk, \"list\");\n readBytesAsString(presetChunk.chunkData, 4);\n \n // read the hydra chunks\n const presetHeadersChunk = readRIFFChunk(presetChunk.chunkData);\n this.verifyHeader(presetHeadersChunk, \"phdr\");\n \n const presetZonesChunk = readRIFFChunk(presetChunk.chunkData);\n this.verifyHeader(presetZonesChunk, \"pbag\");\n \n const presetModulatorsChunk = readRIFFChunk(presetChunk.chunkData);\n this.verifyHeader(presetModulatorsChunk, \"pmod\");\n \n const presetGeneratorsChunk = readRIFFChunk(presetChunk.chunkData);\n this.verifyHeader(presetGeneratorsChunk, \"pgen\");\n \n const presetInstrumentsChunk = readRIFFChunk(presetChunk.chunkData);\n this.verifyHeader(presetInstrumentsChunk, \"inst\");\n \n const presetInstrumentZonesChunk = readRIFFChunk(presetChunk.chunkData);\n this.verifyHeader(presetInstrumentZonesChunk, \"ibag\");\n \n const presetInstrumentModulatorsChunk = readRIFFChunk(presetChunk.chunkData);\n this.verifyHeader(presetInstrumentModulatorsChunk, \"imod\");\n \n const presetInstrumentGeneratorsChunk = readRIFFChunk(presetChunk.chunkData);\n this.verifyHeader(presetInstrumentGeneratorsChunk, \"igen\");\n \n const presetSamplesChunk = readRIFFChunk(presetChunk.chunkData);\n this.verifyHeader(presetSamplesChunk, \"shdr\");\n \n /**\n * read all the samples\n * (the current index points to start of the smpl read)\n */\n this.dataArray.currentIndex = this.sampleDataStartIndex;\n this.samples.push(...readSamples(presetSamplesChunk, sampleData, !isSF2Pack));\n \n /**\n * read all the instrument generators\n * @type {Generator[]}\n */\n let instrumentGenerators = readGenerators(presetInstrumentGeneratorsChunk);\n \n /**\n * read all the instrument modulators\n * @type {Modulator[]}\n */\n let instrumentModulators = readModulators(presetInstrumentModulatorsChunk);\n \n /**\n * read all the instrument zones\n * @type {InstrumentZone[]}\n */\n let instrumentZones = readInstrumentZones(\n presetInstrumentZonesChunk,\n instrumentGenerators,\n instrumentModulators,\n this.samples\n );\n \n this.instruments = readInstruments(presetInstrumentsChunk, instrumentZones);\n \n /**\n * read all the preset generators\n * @type {Generator[]}\n */\n let presetGenerators = readGenerators(presetGeneratorsChunk);\n \n /**\n * Read all the preset modulatorrs\n * @type {Modulator[]}\n */\n let presetModulators = readModulators(presetModulatorsChunk);\n \n let presetZones = readPresetZones(presetZonesChunk, presetGenerators, presetModulators, this.instruments);\n \n this.presets.push(...readPresets(presetHeadersChunk, presetZones, this));\n this.presets.sort((a, b) => (a.program - b.program) + (a.bank - b.bank));\n this._parseInternal();\n SpessaSynthInfo(\n `%cParsing finished! %c\"${this.soundFontInfo[\"INAM\"]}\"%c has %c${this.presets.length} %cpresets,\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 if (isSF2Pack)\n {\n delete this.dataArray;\n }\n }\n \n /**\n * @param chunk {RiffChunk}\n * @param expected {string}\n */\n verifyHeader(chunk, expected)\n {\n if (chunk.header.toLowerCase() !== expected.toLowerCase())\n {\n SpessaSynthGroupEnd();\n this.parsingError(`Invalid chunk header! Expected \"${expected.toLowerCase()}\" got \"${chunk.header.toLowerCase()}\"`);\n }\n }\n \n /**\n * @param text {string}\n * @param expected {string}\n */\n verifyText(text, expected)\n {\n if (text.toLowerCase() !== expected.toLowerCase())\n {\n SpessaSynthGroupEnd();\n this.parsingError(`Invalid FourCC: Expected \"${expected.toLowerCase()}\" got \"${text.toLowerCase()}\"\\``);\n }\n }\n \n destroySoundBank()\n {\n super.destroySoundBank();\n delete this.dataArray;\n }\n}", "import { IndexedByteArray } from \"../utils/indexed_array.js\";\nimport { readBytesAsString } from \"../utils/byte_functions/string.js\";\nimport { DLSSoundFont } from \"./dls/dls_soundfont.js\";\nimport { SoundFont2 } from \"./read_sf2/soundfont.js\";\n\n/**\n * Loads a soundfont file\n * @param buffer {ArrayBuffer}\n * @returns {BasicSoundBank}\n */\nexport function loadSoundFont(buffer)\n{\n const check = buffer.slice(8, 12);\n const a = new IndexedByteArray(check);\n const id = readBytesAsString(a, 4, undefined, false).toLowerCase();\n if (id === \"dls \")\n {\n return new DLSSoundFont(buffer);\n }\n return new SoundFont2(buffer, false);\n}", "import { SpessaSynthWarn } from \"../../../utils/loggin.js\";\nimport { loadSoundFont } from \"../../../soundfont/load_soundfont.js\";\nimport { isXGDrums } from \"../../../utils/xg_hacks.js\";\n\n/**\n * @typedef {Object} SoundFontType\n * @property {string} id - unique id for the soundfont\n * @property {BasicSoundBank} soundfont - the soundfont itself\n * @property {number} bankOffset - the soundfont's bank offset\n */\n\nexport class SoundFontManager\n{\n /**\n * Creates a new instance of soundfont manager\n * @param initialSoundFontBuffer {ArrayBuffer} Array buffer of the soundfont. This soudfont always has the id \"main\"\n */\n constructor(initialSoundFontBuffer)\n {\n this.reloadManager(initialSoundFontBuffer);\n }\n \n generatePresetList()\n {\n /**\n * <\"bank-program\", \"presetName\">\n * @type {Object<string, string>}\n */\n const presetList = {};\n // gather the presets in reverse and replace if necessary\n for (let i = this.soundfontList.length - 1; i >= 0; i--)\n {\n const font = this.soundfontList[i];\n /**\n * prevent preset names from the same soudfont from being overriden\n * if the soundfont has two presets with matching bank and program\n * @type {Set<string>}\n */\n const presets = new Set();\n for (const p of font.soundfont.presets)\n {\n const presetString = `${p.bank + font.bankOffset}-${p.program}`;\n if (presets.has(presetString))\n {\n continue;\n }\n presets.add(presetString);\n presetList[presetString] = p.presetName;\n }\n }\n \n /**\n * @type {{bank: number, presetName: string, program: number}[]}\n */\n this.presetList = [];\n for (const [string, name] of Object.entries(presetList))\n {\n const pb = string.split(\"-\");\n this.presetList.push({\n presetName: name,\n program: parseInt(pb[1]),\n bank: parseInt(pb[0])\n });\n }\n }\n \n /**\n * Get the final preset list\n * @returns {{bank: number, presetName: string, program: number}[]}\n */\n getPresetList()\n {\n return this.presetList.slice();\n }\n \n /**\n * Clears all soundfonts and adds a new one\n * @param soundFontArrayBuffer {ArrayBuffer}\n */\n reloadManager(soundFontArrayBuffer)\n {\n const font = loadSoundFont(soundFontArrayBuffer);\n /**\n * All the soundfonts, ordered from the most important to the least.\n * @type {SoundFontType[]}\n */\n this.soundfontList = [];\n this.soundfontList.push({\n id: \"main\",\n bankOffset: 0,\n soundfont: font\n });\n this.generatePresetList();\n }\n \n deleteSoundFont(id)\n {\n if (this.soundfontList.length === 0)\n {\n SpessaSynthWarn(\"1 soundfont left. Aborting!\");\n return;\n }\n const index = this.soundfontList.findIndex(s => s.id === id);\n if (index === -1)\n {\n SpessaSynthWarn(`No soundfont with id of \"${id}\" found. Aborting!`);\n return;\n }\n delete this.soundfontList[index].soundfont.presets;\n delete this.soundfontList[index].soundfont.instruments;\n delete this.soundfontList[index].soundfont.samples;\n this.soundfontList.splice(index, 1);\n this.generatePresetList();\n }\n \n /**\n * Adds a new soundfont buffer with a given ID\n * @param buffer {ArrayBuffer}\n * @param id {string}\n * @param bankOffset {number}\n */\n addNewSoundFont(buffer, id, bankOffset)\n {\n if (this.soundfontList.find(s => s.id === id) !== undefined)\n {\n throw new Error(\"Cannot overwrite the existing soundfont. Use soundfontManager.delete(id) instead.\");\n }\n this.soundfontList.push({\n id: id,\n soundfont: loadSoundFont(buffer),\n bankOffset: bankOffset\n });\n this.generatePresetList();\n }\n \n /**\n * Rearranges the soundfonts\n * @param newList {string[]} the order of soundfonts, a list of strings, first overwrites second\n */\n rearrangeSoundFonts(newList)\n {\n this.soundfontList.sort((a, b) =>\n newList.indexOf(a.id) - newList.indexOf(b.id)\n );\n this.generatePresetList();\n }\n \n /**\n * Gets a given preset from the soundfont stack\n * @param bankNumber {number}\n * @param programNumber {number}\n * @param allowXGDrums {boolean} if true, allows XG drum banks (120, 126 and 127) as drum preset\n * @returns {BasicPreset} the preset\n */\n getPreset(bankNumber, programNumber, allowXGDrums = false)\n {\n if (this.soundfontList.length < 1)\n {\n throw new Error(\"No soundfonts! This should never happen.\");\n }\n for (const sf of this.soundfontList)\n {\n // check for the preset (with given offset)\n const preset = sf.soundfont.getPresetNoFallback(\n bankNumber - sf.bankOffset,\n programNumber,\n allowXGDrums\n );\n if (preset !== undefined)\n {\n return preset;\n }\n // if not found, advance to the next soundfont\n }\n const isDrum = bankNumber === 128 || (allowXGDrums && isXGDrums(bankNumber));\n // if none found, return the first correct preset found\n if (!isDrum)\n {\n for (const sf of this.soundfontList)\n {\n const preset = sf.soundfont.presets.find(p => p.program === programNumber && !p.isDrumPreset(\n allowXGDrums));\n if (preset)\n {\n return preset;\n }\n }\n // if nothing at all, use the first preset\n return this.soundfontList[0].soundfont.presets[0];\n }\n else\n {\n for (const sf of this.soundfontList)\n {\n // check for any drum type (127/128) and matching program\n const p = sf.soundfont.presets.find(p => p.isDrumPreset(allowXGDrums) && p.program === programNumber);\n if (p)\n {\n return p;\n }\n // check for any drum preset\n const preset = sf.soundfont.presets.find(p => p.isDrumPreset(allowXGDrums));\n if (preset)\n {\n return preset;\n }\n }\n // if nothing at all, use the first preset\n return this.soundfontList[0].soundfont.presets[0];\n }\n }\n \n destroyManager()\n {\n this.soundfontList.forEach(s =>\n {\n s.soundfont.destroySoundBank();\n });\n delete this.soundfontList;\n }\n}", "/**\n * A manager for custom key overrides for channels\n */\n\nexport class KeyModifier\n{\n \n /**\n * The new override velocity. -1 means unchanged\n * @type {number}\n */\n velocity = -1;\n /**\n * The patch this key uses. -1 on either means default\n * @type {{bank: number, program: number}}\n */\n patch = { bank: -1, program: -1 };\n \n /**\n * Linear gain override for the voice\n */\n gain = 1;\n \n /**\n * @param velocity {number}\n * @param bank {number}\n * @param program {number}\n * @param gain {number}\n */\n constructor(velocity = -1, bank = -1, program = -1, gain = 1)\n {\n this.velocity = velocity;\n this.patch = {\n bank: bank,\n program: program\n };\n this.gain = gain;\n }\n}\n\nexport class KeyModifierManager\n{\n /**\n * The velocity override mappings for MIDI keys\n * stored as [channelNumber][midiNote]\n * @type {KeyModifier[][]}\n * @private\n */\n _keyMappings = [];\n \n // noinspection JSUnusedGlobalSymbols\n /**\n * @param channel {number}\n * @param midiNote {number}\n * @param mapping {KeyModifier}\n */\n addMapping(channel, midiNote, mapping)\n {\n if (this._keyMappings[channel] === undefined)\n {\n this._keyMappings[channel] = [];\n }\n this._keyMappings[channel][midiNote] = mapping;\n }\n \n // noinspection JSUnusedGlobalSymbols\n /**\n * @param channel {number}\n * @param midiNote {number}\n */\n deleteMapping(channel, midiNote)\n {\n if (this._keyMappings[channel]?.[midiNote] === undefined)\n {\n return;\n }\n this._keyMappings[channel][midiNote] = undefined;\n }\n \n // noinspection JSUnusedGlobalSymbols\n /**\n * Clear all mappings\n */\n clearMappings()\n {\n this._keyMappings = [];\n }\n \n /**\n * @param mappings {KeyModifier[][]}\n */\n setMappings(mappings)\n {\n this._keyMappings = mappings;\n }\n \n /**\n * @returns {KeyModifier[][]}\n */\n getMappings()\n {\n return this._keyMappings;\n }\n \n /**\n * @param channel {number}\n * @param midiNote {number}\n * @returns {number} velocity, -1 if unchanged\n */\n getVelocity(channel, midiNote)\n {\n return this._keyMappings[channel]?.[midiNote]?.velocity ?? -1;\n }\n \n /**\n * @param channel {number}\n * @param midiNote {number}\n * @returns {number} linear gain\n */\n getGain(channel, midiNote)\n {\n return this._keyMappings[channel]?.[midiNote]?.gain ?? 1;\n }\n \n /**\n * @param channel {number}\n * @param midiNote {number}\n * @returns {boolean}\n */\n hasOverridePatch(channel, midiNote)\n {\n const bank = this._keyMappings[channel]?.[midiNote]?.patch?.bank;\n return bank !== undefined && bank >= 0;\n }\n \n /**\n * @param channel {number}\n * @param midiNote {number}\n * @returns {{bank: number, program: number}} -1 if unchanged\n */\n getPatch(channel, midiNote)\n {\n const modifier = this._keyMappings[channel]?.[midiNote];\n if (modifier)\n {\n return modifier.patch;\n }\n throw new Error(\"No modifier.\");\n }\n \n}", "import { absCentsToHz, decibelAttenuationToGain } from \"./unit_converter.js\";\nimport { generatorTypes } from \"../../../soundfont/basic_soundfont/generator.js\";\n\n/**\n * lowpass_filter.js\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/**\n * @typedef {Object} CachedCoefficient\n * @property {number} a0 - Filter coefficient 1\n * @property {number} a1 - Filter coefficient 2\n * @property {number} a2 - Filter coefficient 3\n * @property {number} a3 - Filter coefficient 4\n * @property {number} a4 - Filter coefficient 5\n */\n\nexport class LowpassFilter\n{\n /**\n * Cached coefficient calculations\n * stored as cachedCoefficients[resonanceCb][currentInitialFc]\n * @type {CachedCoefficient[][]}\n * @private\n */\n static cachedCoefficients = [];\n /**\n * Filter coefficient 1\n * @type {number}\n */\n a0 = 0;\n \n /**\n * Filter coefficient 2\n * @type {number}\n */\n a1 = 0;\n \n /**\n * Filter coefficient 3\n * @type {number}\n */\n a2 = 0;\n \n /**\n * Filter coefficient 4\n * @type {number}\n */\n a3 = 0;\n \n /**\n * Filter coefficient 5\n * @type {number}\n */\n a4 = 0;\n \n /**\n * Input history 1\n * @type {number}\n */\n x1 = 0;\n \n /**\n * Input history 2\n * @type {number}\n */\n x2 = 0;\n \n /**\n * Output history 1\n * @type {number}\n */\n y1 = 0;\n \n /**\n * Output history 2\n * @type {number}\n */\n y2 = 0;\n \n /**\n * Resonance in centibels\n * @type {number}\n */\n resonanceCb = 0;\n \n /**\n * Cutoff frequency in absolute cents\n * @type {number}\n */\n currentInitialFc = 13500;\n \n /**\n * For tracking the last cutoff frequency in the apply method, absolute cents\n * Set to infinity to force recalculation\n * @type {number}\n */\n lastTargetCutoff = Infinity;\n \n /**\n * used for tracking if the filter has been initialized\n * @type {boolean}\n */\n initialized = false;\n /**\n * Hertz\n * @type {number}\n */\n sampleRate;\n \n /**\n * @param sampleRate {number}\n */\n constructor(sampleRate)\n {\n this.sampleRate = sampleRate;\n /**\n * @type {number}\n */\n this.maxCutoff = sampleRate * 0.45;\n }\n \n /**\n * Applies a low-pass filter to the given buffer\n * @param voice {Voice} the voice we're working on\n * @param outputBuffer {Float32Array} the buffer to apply the filter to\n * @param fcExcursion {number} the addition of modenv and mod lfo in cents to the filter\n * @param smoothingFactor {number} filter's cutoff frequency smoothing factor\n */\n static apply(voice, outputBuffer, fcExcursion, smoothingFactor)\n {\n const initialFc = voice.modulatedGenerators[generatorTypes.initialFilterFc];\n const filter = voice.filter;\n \n \n if (!filter.initialized)\n {\n // filter initialization, set the current fc to target\n filter.initialized = true;\n filter.currentInitialFc = initialFc;\n }\n else\n {\n /* Note:\n * We only smooth out the initialFc part,\n * the modulation envelope and LFO excursions are not smoothed.\n */\n filter.currentInitialFc += (initialFc - filter.currentInitialFc) * smoothingFactor;\n }\n \n // the final cutoff for this calculation\n const targetCutoff = filter.currentInitialFc + fcExcursion;\n const modulatedResonance = 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 (filter.currentInitialFc > 13499 && targetCutoff > 13499 && 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 (Math.abs(filter.lastTargetCutoff - targetCutoff) > 1 || 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 {\n let input = outputBuffer[i];\n let filtered = 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 * @param filter {LowpassFilter}\n * @param cutoffCents {number}\n */\n static calculateCoefficients(filter, cutoffCents)\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 {\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 sfspec 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 \n // note: no sin or cos tables here as the coefficients are cached\n let w = 2 * Math.PI * cutoffHz / filter.sampleRate;\n let cosw = Math.cos(w);\n let alpha = Math.sin(w) / (2 * resonanceGain);\n \n let b1 = (1 - cosw) * qGain;\n let b0 = b1 / 2;\n let b2 = b0;\n let a0 = 1 + alpha;\n let a1 = -2 * cosw;\n let a2 = 1 - alpha;\n \n /**\n * set coefficients\n * @type {CachedCoefficient}\n */\n const toCache = {};\n toCache.a0 = b0 / a0;\n toCache.a1 = b1 / a0;\n toCache.a2 = b2 / a0;\n toCache.a3 = a1 / a0;\n toCache.a4 = a2 / a0;\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 if (LowpassFilter.cachedCoefficients[qCb] === undefined)\n {\n LowpassFilter.cachedCoefficients[qCb] = [];\n }\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// sfspec section 8.1.3: initialFilterFc ranges from 1500 to 13,500 cents\nfor (let i = 1500; i < 13500; i++)\n{\n dummy.currentInitialFc = i;\n LowpassFilter.calculateCoefficients(dummy, i);\n}\n", "import { modulatorCurveTypes } from \"../../../soundfont/basic_soundfont/modulator.js\";\n\n/**\n * modulator_curves.js\n * precomputes modulator concave and conves curves and calculates a curve value for a given polarity, direction and type\n */\n\n// the length of the precomputed curve tables\nexport const MOD_PRECOMPUTED_LENGTH = 16384;\n\n// Precalculate lookup tables for concave and convex curves\nconst concave = new Float32Array(MOD_PRECOMPUTED_LENGTH + 1);\nconst convex = new Float32Array(MOD_PRECOMPUTED_LENGTH + 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 < MOD_PRECOMPUTED_LENGTH - 1; i++)\n{\n let x = (-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 polarity {number} 0 or 1\n * @param direction {number} 0 or 1\n * @param curveType {number} see modulatorCurveTypes in modulators.js\n * @param value {number} the linear value, 0 to 1\n * @returns {number} the transformed value, 0 to 1, or -1 to 1\n */\nexport function getModulatorCurveValue(direction, curveType, value, polarity)\n{\n // inverse the value if needed\n if (direction)\n {\n value = 1 - value;\n }\n switch (curveType)\n {\n case modulatorCurveTypes.linear:\n if (polarity)\n {\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 (polarity)\n {\n // multiply\n return value * 2 - 1;\n }\n return value;\n \n case modulatorCurveTypes.concave:\n // look up the value\n if (polarity)\n {\n value = value * 2 - 1;\n if (value < 0)\n {\n return -concave[~~(value * -MOD_PRECOMPUTED_LENGTH)];\n }\n return concave[~~(value * MOD_PRECOMPUTED_LENGTH)];\n }\n return concave[~~(value * MOD_PRECOMPUTED_LENGTH)];\n \n case modulatorCurveTypes.convex:\n // look up the value\n if (polarity)\n {\n value = value * 2 - 1;\n if (value < 0)\n {\n return -convex[~~(value * -MOD_PRECOMPUTED_LENGTH)];\n }\n return convex[~~(value * MOD_PRECOMPUTED_LENGTH)];\n }\n return convex[~~(value * MOD_PRECOMPUTED_LENGTH)];\n }\n}\n", "import { timecentsToSeconds } from \"./unit_converter.js\";\nimport { getModulatorCurveValue } from \"./modulator_curves.js\";\nimport { generatorTypes } from \"../../../soundfont/basic_soundfont/generator.js\";\nimport { modulatorCurveTypes } from \"../../../soundfont/basic_soundfont/modulator.js\";\n\n/**\n * modulation_envelope.js\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{\n // this makes the db linear (I think)\n CONVEX_ATTACK[i] = getModulatorCurveValue(0, modulatorCurveTypes.convex, i / 1000, 0);\n}\n\nexport class ModulationEnvelope\n{\n /**\n * The attack duration, in seconds\n * @type {number}\n */\n attackDuration = 0;\n /**\n * The decay duration, in seconds\n * @type {number}\n */\n decayDuration = 0;\n \n /**\n * The hold duration, in seconds\n * @type {number}\n */\n holdDuration = 0;\n \n /**\n * Release duration, in seconds\n * @type {number}\n */\n releaseDuration = 0;\n \n /**\n * The sustain level 0-1\n * @type {number}\n */\n sustainLevel = 0;\n \n /**\n * Delay phase end time in seconds, absolute (audio context time)\n * @type {number}\n */\n delayEnd = 0;\n /**\n * Attack phase end time in seconds, absolute (audio context time)\n * @type {number}\n */\n attackEnd = 0;\n /**\n * Hold phase end time in seconds, absolute (audio context time)\n * @type {number}\n */\n holdEnd = 0;\n /**\n * Decay phase end time in seconds, absolute (audio context time)\n * @type {number}\n */\n decayEnd = 0;\n \n /**\n * The level of the envelope when the release phase starts\n * @type {number}\n */\n releaseStartLevel = 0;\n \n /**\n * The current modulation envelope value\n * @type {number}\n */\n currentValue = 0;\n \n /**\n * Starts the release phase in the envelope\n * @param voice {Voice} the voice this envelope belongs to\n */\n static startRelease(voice)\n {\n ModulationEnvelope.recalculate(voice);\n }\n \n /**\n * @param voice {Voice} the voice to recalculate\n */\n static recalculate(voice)\n {\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 {\n env.releaseStartLevel = ModulationEnvelope.getValue(voice, voice.releaseStartTime, true);\n }\n \n env.sustainLevel = 1 - (voice.modulatedGenerators[generatorTypes.sustainModEnv] / 1000);\n \n env.attackDuration = timecentsToSeconds(voice.modulatedGenerators[generatorTypes.attackModEnv]);\n \n const decayKeyExcursionCents = ((60 - voice.midiNote) * voice.modulatedGenerators[generatorTypes.keyNumToModEnvDecay]);\n const decayTime = timecentsToSeconds(voice.modulatedGenerators[generatorTypes.decayModEnv] + decayKeyExcursionCents);\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 = ((60 - voice.midiNote) * voice.modulatedGenerators[generatorTypes.keyNumToModEnvHold]);\n env.holdDuration = timecentsToSeconds(holdKeyExcursionCents + voice.modulatedGenerators[generatorTypes.holdModEnv]);\n \n const releaseTime = timecentsToSeconds(voice.modulatedGenerators[generatorTypes.releaseModEnv]);\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 = voice.startTime + timecentsToSeconds(voice.modulatedGenerators[generatorTypes.delayModEnv]);\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 {Voice} the voice we are working on\n * @param currentTime {number} in seconds\n * @param ignoreRelease {boolean} if true, it will compute the value as if the voice was not released\n * @returns {number} modenv value, from 0 to 1\n */\n static getValue(voice, currentTime, ignoreRelease = false)\n {\n const env = voice.modulationEnvelope;\n if (voice.isInRelease && !ignoreRelease)\n {\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 {\n return 0;\n }\n return Math.max(\n 0,\n (1 - (currentTime - voice.releaseStartTime) / env.releaseDuration) * env.releaseStartLevel\n );\n }\n \n if (currentTime < env.delayEnd)\n {\n env.currentValue = 0; // delay\n }\n else if (currentTime < env.attackEnd)\n {\n // modulation envelope uses convex curve for attack\n env.currentValue = CONVEX_ATTACK[~~((1 - (env.attackEnd - currentTime) / env.attackDuration) * 1000)];\n }\n else if (currentTime < env.holdEnd)\n {\n // hold: stay at 1\n env.currentValue = MODENV_PEAK;\n }\n else if (currentTime < env.decayEnd)\n {\n // decay: linear ramp from 1 to sustain level\n env.currentValue = (1 - (env.decayEnd - currentTime) / env.decayDuration) * (env.sustainLevel - MODENV_PEAK) + MODENV_PEAK;\n }\n else\n {\n // sustain: stay at sustain level\n env.currentValue = env.sustainLevel;\n }\n return env.currentValue;\n }\n}", "/**\n * voice.js\n * purpose: prepares Voices from sample and generator data\n */\nimport { MIN_EXCLUSIVE_LENGTH, MIN_NOTE_LENGTH } from \"../main_processor.js\";\nimport { SpessaSynthWarn } from \"../../../utils/loggin.js\";\nimport { LowpassFilter } from \"./lowpass_filter.js\";\nimport { VolumeEnvelope } from \"./volume_envelope.js\";\nimport { ModulationEnvelope } from \"./modulation_envelope.js\";\nimport { addAndClampGenerator, generatorTypes } from \"../../../soundfont/basic_soundfont/generator.js\";\nimport { Modulator } from \"../../../soundfont/basic_soundfont/modulator.js\";\nimport { isSystemXG } from \"../../../utils/xg_hacks.js\";\n\nconst EXCLUSIVE_CUTOFF_TIME = -2320;\nconst EXCLUSIVE_MOD_CUTOFF_TIME = -1130; // less because filter shenanigans\n\nclass AudioSample\n{\n /**\n * the sample's audio data\n * @type {Float32Array}\n */\n sampleData;\n /**\n * Current playback step (rate)\n * @type {number}\n */\n playbackStep = 0;\n /**\n * Current position in the sample\n * @type {number}\n */\n cursor = 0;\n /**\n * MIDI root key of the sample\n * @type {number}\n */\n rootKey = 0;\n /**\n * Start position of the loop\n * @type {number}\n */\n loopStart = 0;\n /**\n * End position of the loop\n * @type {number}\n */\n loopEnd = 0;\n /**\n * End position of the sample\n * @type {number}\n */\n 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 * @type {0|1|2|3}\n */\n loopingMode = 0;\n /**\n * Indicates if the sample is currently looping\n * @type {boolean}\n */\n isLooping = false;\n \n /**\n * @param data {Float32Array}\n * @param playbackStep {number} the playback step, a single increment\n * @param cursorStart {number} the sample id which starts the playback\n * @param rootKey {number} MIDI root key\n * @param loopStart {number} loop start index\n * @param loopEnd {number} loop end index\n * @param endIndex {number} sample end index (for end offset)\n * @param loopingMode {number} sample looping mode\n */\n constructor(\n data,\n playbackStep,\n cursorStart,\n rootKey,\n loopStart,\n loopEnd,\n endIndex,\n loopingMode\n )\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\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 */\nclass Voice\n{\n /**\n * The sample of the voice.\n * @type {AudioSample}\n */\n sample;\n \n /**\n * Lowpass filter applied to the voice.\n * @type {LowpassFilter}\n */\n filter;\n \n /**\n * Linear gain of the voice. Used with Key Modifiers.\n * @type {number}\n */\n gain = 1;\n \n /**\n * The unmodulated (copied to) generators of the voice.\n * @type {Int16Array}\n */\n generators;\n \n /**\n * The voice's modulators.\n * @type {Modulator[]}\n */\n modulators = [];\n \n /**\n * The generators in real-time, affected by modulators.\n * This is used during rendering.\n * @type {Int16Array}\n */\n modulatedGenerators;\n \n /**\n * Indicates if the voice is finished.\n * @type {boolean}\n */\n finished = false;\n \n /**\n * Indicates if the voice is in the release phase.\n * @type {boolean}\n */\n isInRelease = false;\n \n /**\n * MIDI channel number.\n * @type {number}\n */\n channelNumber = 0;\n \n /**\n * Velocity of the note.\n * @type {number}\n */\n velocity = 0;\n \n /**\n * MIDI note number.\n * @type {number}\n */\n midiNote = 0;\n \n /**\n * The pressure of the voice\n * @type {number}\n */\n pressure = 0;\n \n /**\n * Target key for the note.\n * @type {number}\n */\n targetKey = 0;\n \n /**\n * Modulation envelope.\n * @type {ModulationEnvelope}\n */\n modulationEnvelope = new ModulationEnvelope();\n \n /**\n * Volume envelope.\n * @type {VolumeEnvelope}\n */\n volumeEnvelope;\n \n /**\n * Start time of the voice, absolute.\n * @type {number}\n */\n startTime = 0;\n \n /**\n * Start time of the release phase, absolute.\n * @type {number}\n */\n releaseStartTime = Infinity;\n \n /**\n * Current tuning in cents.\n * @type {number}\n */\n currentTuningCents = 0;\n \n /**\n * Current calculated tuning. (as in ratio)\n * @type {number}\n */\n currentTuningCalculated = 1;\n \n /**\n * From -500 to 500.\n * @param {number}\n */\n 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 #29 comment by @paulikaro\n * @type {number}\n */\n realKey;\n \n /**\n * @type {number} Initial key to glide from, MIDI Note number. If -1, the portamento is OFF.\n */\n portamentoFromKey = -1;\n \n /**\n * Duration of the linear glide, in seconds.\n * @type {number}\n */\n portamentoDuration = 0;\n \n /**\n * From -500 to 500, where zero means disabled (use the channel pan). Used for random pan.\n * @type {number}\n */\n overridePan = 0;\n \n /**\n * Exclusive class number for hi-hats etc.\n * @type {number}\n */\n exclusiveClass = 0;\n \n /**\n * Creates a Voice\n * @param sampleRate {number}\n * @param audioSample {AudioSample}\n * @param midiNote {number}\n * @param velocity {number}\n * @param channel {number}\n * @param currentTime {number}\n * @param targetKey {number}\n * @param realKey {number}\n * @param generators {Int16Array}\n * @param modulators {Modulator[]}\n */\n constructor(\n sampleRate,\n audioSample,\n midiNote,\n velocity,\n channel,\n currentTime,\n targetKey,\n realKey,\n generators,\n modulators\n )\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 \n this.velocity = velocity;\n this.midiNote = midiNote;\n this.channelNumber = channel;\n this.startTime = currentTime;\n this.targetKey = targetKey;\n this.realKey = realKey;\n this.volumeEnvelope = new VolumeEnvelope(sampleRate, generators[generatorTypes.sustainVolEnv]);\n }\n \n /**\n * copies the voice\n * @param voice {Voice}\n * @param currentTime {number}\n * @param realKey {number}\n * @returns Voice\n */\n static copy(voice, currentTime, realKey)\n {\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 voice.channelNumber,\n currentTime,\n voice.targetKey,\n realKey,\n voice.generators,\n voice.modulators.map(m => Modulator.copy(m))\n );\n }\n \n /**\n * Releases the voice as exclusiveClass\n * @param currentTime {number}\n */\n exclusiveRelease(currentTime)\n {\n this.release(currentTime, MIN_EXCLUSIVE_LENGTH);\n this.modulatedGenerators[generatorTypes.releaseVolEnv] = EXCLUSIVE_CUTOFF_TIME; // make the release nearly instant\n this.modulatedGenerators[generatorTypes.releaseModEnv] = EXCLUSIVE_MOD_CUTOFF_TIME;\n VolumeEnvelope.recalculate(this);\n ModulationEnvelope.recalculate(this);\n }\n \n /**\n * Stops the voice\n * @param currentTime {number}\n * @param minNoteLength {number} minimum note length in seconds\n */\n release(currentTime, minNoteLength = MIN_NOTE_LENGTH)\n {\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 {\n this.releaseStartTime = this.startTime + minNoteLength;\n }\n }\n}\n\n/**\n * @param channel {number} a hint for the processor to recalculate sample cursors when sample dumping\n * @param midiNote {number} the MIDI note to use\n * @param velocity {number} the velocity to use\n * @param realKey {number} the real MIDI note if the \"midiNote\" was changed by MIDI Tuning Standard\n * @this {SpessaSynthProcessor}\n * @returns {Voice[]} output is an array of Voices\n */\nexport function getVoices(channel,\n midiNote,\n velocity,\n realKey)\n{\n /**\n * @type {Voice[]}\n */\n let voices;\n const channelObject = this.midiAudioChannels[channel];\n \n // override patch\n const overridePatch = this.keyModifierManager.hasOverridePatch(channel, midiNote);\n \n let bank = channelObject.getBankSelect();\n let program = channelObject.preset.program;\n if (overridePatch)\n {\n const override = this.keyModifierManager.getPatch(channel, midiNote);\n bank = override.bank;\n program = override.program;\n }\n \n const cached = this.getCachedVoice(bank, program, midiNote, velocity);\n // if cached, return it!\n if (cached !== undefined)\n {\n return cached.map(v => Voice.copy(v, this.currentSynthTime, realKey));\n }\n \n // not cached...\n let preset = channelObject.preset;\n if (overridePatch)\n {\n preset = this.soundfontManager.getPreset(bank, program, isSystemXG(this.system));\n }\n /**\n * @returns {Voice[]}\n */\n voices = preset.getSamplesAndGenerators(midiNote, velocity)\n .reduce((voices, sampleAndGenerators) =>\n {\n if (sampleAndGenerators.sample.getAudioData() === undefined)\n {\n SpessaSynthWarn(`Discarding invalid sample: ${sampleAndGenerators.sample.sampleName}`);\n return voices;\n }\n \n // create the generator list\n const generators = new Int16Array(60);\n // apply and sum the gens\n for (let i = 0; i < 60; i++)\n {\n generators[i] = addAndClampGenerator(\n i,\n sampleAndGenerators.presetGenerators,\n sampleAndGenerators.instrumentGenerators\n );\n }\n \n // !! EMU initial attenuation correction, multiply initial attenuation by 0.4\n generators[generatorTypes.initialAttenuation] = Math.floor(generators[generatorTypes.initialAttenuation] * 0.4);\n \n // key override\n let rootKey = sampleAndGenerators.sample.samplePitch;\n if (generators[generatorTypes.overridingRootKey] > -1)\n {\n rootKey = generators[generatorTypes.overridingRootKey];\n }\n \n let targetKey = midiNote;\n if (generators[generatorTypes.keyNum] > -1)\n {\n targetKey = generators[generatorTypes.keyNum];\n }\n \n // determine looping mode now. if the loop is too small, disable\n let loopStart = sampleAndGenerators.sample.sampleLoopStartIndex;\n let loopEnd = sampleAndGenerators.sample.sampleLoopEndIndex;\n let loopingMode = generators[generatorTypes.sampleModes];\n /**\n * create the sample\n * offsets are calculated at note on time (to allow for modulation of them)\n * @type {AudioSample}\n */\n const audioSample = new AudioSample(\n sampleAndGenerators.sample.sampleData,\n (sampleAndGenerators.sample.sampleRate / this.sampleRate) * Math.pow(\n 2,\n sampleAndGenerators.sample.samplePitchCorrection / 1200\n ), // cent tuning\n 0,\n rootKey,\n loopStart,\n loopEnd,\n Math.floor(sampleAndGenerators.sample.sampleData.length) - 1,\n loopingMode\n );\n // velocity override\n if (generators[generatorTypes.velocity] > -1)\n {\n velocity = generators[generatorTypes.velocity];\n }\n \n // uncomment to print debug info\n // SpessaSynthTable([{\n // Sample: sampleAndGenerators.sample.sampleName,\n // Generators: generators,\n // Modulators: sampleAndGenerators.modulators.map(m => Modulator.debugString(m)),\n // Velocity: velocity,\n // TargetKey: targetKey,\n // MidiNote: midiNote,\n // AudioSample: audioSample\n // }]);\n \n \n voices.push(\n new Voice(\n this.sampleRate,\n audioSample,\n midiNote,\n velocity,\n channel,\n this.currentSynthTime,\n targetKey,\n realKey,\n generators,\n sampleAndGenerators.modulators.map(m => Modulator.copy(m))\n )\n );\n return voices;\n }, []);\n // cache the voice\n this.setCachedVoice(bank, program, midiNote, velocity, voices.map(v =>\n Voice.copy(v, this.currentSynthTime, realKey)));\n return voices;\n}", "import { generatorTypes } from \"../../../soundfont/basic_soundfont/generator.js\";\n\n/**\n * stereo_panner.js\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\nexport const REVERB_DIVIDER = 4600;\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{\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 {Voice} the voice to pan\n * @param inputBuffer {Float32Array} the input buffer in mono\n * @param outputLeft {Float32Array} left output buffer\n * @param outputRight {Float32Array} right output buffer\n * @param reverbLeft {Float32Array} left reverb input\n * @param reverbRight {Float32Array} right reverb input\n * @param chorusLeft {Float32Array} left chorus buffer\n * @param chorusRight {Float32Array} right chorus buffer\n * @this {MidiAudioChannel}\n */\nexport function panVoice(voice,\n inputBuffer,\n outputLeft, outputRight,\n reverbLeft, reverbRight,\n chorusLeft, chorusRight)\n{\n if (isNaN(inputBuffer[0]))\n {\n return;\n }\n /**\n * clamp -500 to 500\n * @type {number}\n */\n let pan;\n if (voice.overridePan)\n {\n pan = voice.overridePan;\n }\n else\n {\n // smooth out pan to prevent clicking\n voice.currentPan += (voice.modulatedGenerators[generatorTypes.pan] - voice.currentPan) * this.synth.panSmoothingFactor;\n pan = voice.currentPan;\n }\n \n const gain = this.synth.currentGain * voice.gain;\n const index = ~~(pan + 500);\n // get voice's gain levels for each channel\n const gainLeft = panTableLeft[index] * gain * this.synth.panLeft;\n const gainRight = panTableRight[index] * gain * this.synth.panRight;\n \n // disable reverb and chorus if necessary\n if (this.synth.effectsEnabled)\n {\n const reverbSend = voice.modulatedGenerators[generatorTypes.reverbEffectsSend];\n if (reverbSend > 0)\n {\n // reverb is mono so we need to multiply by gain\n const reverbGain = this.synth.reverbGain * gain * (reverbSend / REVERB_DIVIDER);\n for (let i = 0; i < inputBuffer.length; i++)\n {\n reverbLeft[i] += reverbGain * inputBuffer[i];\n }\n // copy as its mono\n reverbRight.set(reverbLeft);\n }\n \n const chorusSend = voice.modulatedGenerators[generatorTypes.chorusEffectsSend];\n if (chorusSend > 0)\n {\n // chorus is stereo so we do not need to\n const chorusGain = this.synth.chorusGain * chorusSend / CHORUS_DIVIDER;\n const chorusLeftGain = gainLeft * chorusGain;\n const chorusRightGain = gainRight * chorusGain;\n for (let i = 0; i < inputBuffer.length; i++)\n {\n chorusLeft[i] += chorusLeftGain * inputBuffer[i];\n chorusRight[i] += chorusRightGain * inputBuffer[i];\n }\n }\n }\n \n // mix down the audio data\n if (gainLeft > 0)\n {\n for (let i = 0; i < inputBuffer.length; i++)\n {\n outputLeft[i] += gainLeft * inputBuffer[i];\n }\n }\n if (gainRight > 0)\n {\n for (let i = 0; i < inputBuffer.length; i++)\n {\n outputRight[i] += gainRight * inputBuffer[i];\n }\n }\n}", "import { SpessaSynthInfo } from \"../../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../../utils/other.js\";\n\n/**\n * @this {SpessaSynthProcessor}\n * @param force {boolean}\n */\nexport function stopAllChannels(force = false)\n{\n SpessaSynthInfo(\"%cStop all received!\", consoleColors.info);\n for (let i = 0; i < this.midiAudioChannels.length; i++)\n {\n this.midiAudioChannels[i].stopAllNotes(force);\n }\n this.callEvent(\"stopall\", undefined);\n}", "/**\n * Sets the embedded (RMI soundfont)\n * @param font {ArrayBuffer}\n * @param offset {number}\n * @this {SpessaSynthProcessor}\n */\nexport function setEmbeddedSoundFont(font, offset)\n{\n // set offset\n this.soundfontBankOffset = offset;\n this.reloadSoundFont(font, true);\n // preload all samples\n this.overrideSoundfont.samples.forEach(s => s.getAudioData());\n \n // apply snapshot again if applicable\n if (this._snapshot !== undefined)\n {\n this.applySynthesizerSnapshot(this._snapshot);\n this.resetAllControllers();\n }\n}", "import { loadSoundFont } from \"../../../../soundfont/load_soundfont.js\";\nimport { SpessaSynthInfo } from \"../../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../../utils/other.js\";\n\n/**\n * @param buffer {ArrayBuffer}\n * @param isOverride {Boolean}\n * @this {SpessaSynthProcessor}\n */\nexport function reloadSoundFont(buffer, isOverride = false)\n{\n this.clearSoundFont(false, isOverride);\n if (isOverride)\n {\n this.overrideSoundfont = loadSoundFont(buffer);\n }\n else\n {\n this.soundfontManager.reloadManager(buffer);\n }\n this.getDefaultPresets();\n this.midiAudioChannels.forEach(c =>\n c.programChange(c.preset.program)\n );\n this.postReady();\n this.sendPresetList();\n SpessaSynthInfo(\"%cSpessaSynth is ready!\", consoleColors.recognized);\n}", "/**\n * @this {SpessaSynthProcessor}\n * @param sendPresets {boolean}\n * @param clearOverride {boolean}\n */\nexport function clearSoundFont(sendPresets = true, clearOverride = true)\n{\n this.stopAllChannels(true);\n if (clearOverride)\n {\n delete this.overrideSoundfont;\n this.overrideSoundfont = undefined;\n }\n this.getDefaultPresets();\n this.cachedVoices = [];\n \n for (let i = 0; i < this.midiAudioChannels.length; i++)\n {\n const channelObject = this.midiAudioChannels[i];\n if (!clearOverride || (clearOverride && channelObject.presetUsesOverride))\n {\n channelObject.setPresetLock(false);\n }\n channelObject.programChange(channelObject.preset.program);\n }\n if (sendPresets)\n {\n this.sendPresetList();\n }\n}", "/**\n * @this {SpessaSynthProcessor}\n */\nexport function sendPresetList()\n{\n /**\n * @type {{bank: number, presetName: string, program: number}[]}\n */\n const mainFont = this.soundfontManager.getPresetList();\n if (this.overrideSoundfont !== undefined)\n {\n this.overrideSoundfont.presets.forEach(p =>\n {\n const bankCheck = p.bank === 128 ? 128 : p.bank + this.soundfontBankOffset;\n const exists = mainFont.find(pr => pr.bank === bankCheck && pr.program === p.program);\n if (exists !== undefined)\n {\n exists.presetName = p.presetName;\n }\n else\n {\n mainFont.push({\n presetName: p.presetName,\n bank: bankCheck,\n program: p.program\n });\n }\n });\n }\n this.callEvent(\"presetlistchange\", mainFont);\n}", "import { isSystemXG } from \"../../../../utils/xg_hacks.js\";\n\n/**\n * @this {SpessaSynthProcessor}\n * @param program {number}\n * @param bank {number}\n * @returns {BasicPreset}\n */\nexport function getPreset(bank, program)\n{\n if (this.overrideSoundfont)\n {\n // if override soundfont\n const bankWithOffset = bank === 128 ? 128 : bank - this.soundfontBankOffset;\n const preset = this.overrideSoundfont.getPresetNoFallback(bankWithOffset, program, isSystemXG(this.system));\n if (preset)\n {\n return preset;\n }\n }\n return this.soundfontManager.getPreset(bank, program, isSystemXG(this.system));\n}", "/**\n * Transposes all channels by given amount of semitones\n * @this {SpessaSynthProcessor}\n * @param semitones {number} Can be float\n * @param force {boolean} defaults to false, if true transposes the channel even if it's a drum channel\n */\nexport function transposeAllChannels(semitones, force = false)\n{\n this.transposition = 0;\n for (let i = 0; i < this.midiAudioChannels.length; i++)\n {\n this.midiAudioChannels[i].transposeChannel(semitones, force);\n }\n this.transposition = semitones;\n}", "import { customControllers } from \"../../engine_components/controller_tables.js\";\n\n/**\n * Sets the synth's primary tuning\n * @this {SpessaSynthProcessor}\n * @param cents {number}\n */\nexport function setMasterTuning(cents)\n{\n cents = Math.round(cents);\n for (let i = 0; i < this.midiAudioChannels.length; i++)\n {\n this.midiAudioChannels[i].setCustomController(customControllers.masterTuning, cents);\n }\n}", "/**\n * Represents a snapshot of a single channel's state in the synthesizer.\n */\nexport class ChannelSnapshot\n{\n /**\n * The channel's MIDI program number.\n * @type {number}\n */\n program;\n \n /**\n * The channel's bank number.\n * @type {number}\n */\n bank;\n \n /**\n * If the bank is LSB. For restoring.\n * @type {boolean}\n */\n isBankLSB;\n \n /**\n * The name of the patch currently loaded in the channel.\n * @type {string}\n */\n patchName;\n \n /**\n * Indicates whether the channel's program change is disabled.\n * @type {boolean}\n */\n lockPreset;\n \n /**\n * Indicates the MIDI system when the preset was locked\n * @type {SynthSystem}\n */\n lockedSystem;\n \n /**\n * The array of all MIDI controllers (in 14-bit values) with the modulator sources at the end.\n * @type {Int16Array}\n */\n midiControllers;\n \n /**\n * An array of booleans, indicating if the controller with a current index is locked.\n * @type {boolean[]}\n */\n lockedControllers;\n \n /**\n * Array of custom (not SF2) control values such as RPN pitch tuning, transpose, modulation depth, etc.\n * @type {Float32Array}\n */\n customControllers;\n \n /**\n * Indicates whether the channel vibrato is locked.\n * @type {boolean}\n */\n lockVibrato;\n \n /**\n * The channel's vibrato settings.\n * @type {Object}\n * @property {number} depth - Vibrato depth, in gain.\n * @property {number} delay - Vibrato delay from note on in seconds.\n * @property {number} rate - Vibrato rate in Hz.\n */\n channelVibrato;\n \n /**\n * Key shift for the channel.\n * @type {number}\n */\n channelTransposeKeyShift;\n \n /**\n * The channel's octave tuning in cents.\n * @type {Int8Array}\n */\n channelOctaveTuning;\n \n /**\n * Indicates whether the channel is muted.\n * @type {boolean}\n */\n isMuted;\n \n /**\n * Overrides velocity if greater than 0, otherwise disabled.\n * @type {number}\n */\n velocityOverride;\n \n /**\n * Indicates whether the channel is a drum channel.\n * @type {boolean}\n */\n drumChannel;\n \n /**\n * Creates a snapshot of a single channel's state in the synthesizer.\n * @param spessaSynthProcessor {SpessaSynthProcessor}\n * @param channelNumber {number}\n * @returns {ChannelSnapshot}\n */\n static getChannelSnapshot(spessaSynthProcessor, channelNumber)\n {\n const channelObject = spessaSynthProcessor.midiAudioChannels[channelNumber];\n const channelSnapshot = new ChannelSnapshot();\n // program data\n channelSnapshot.program = channelObject.preset.program;\n channelSnapshot.bank = channelObject.getBankSelect();\n channelSnapshot.isBankLSB = channelSnapshot.bank !== channelObject.bank;\n channelSnapshot.lockPreset = channelObject.lockPreset;\n channelSnapshot.lockedSystem = channelObject.lockedSystem;\n channelSnapshot.patchName = channelObject.preset.presetName;\n \n // controller data\n channelSnapshot.midiControllers = channelObject.midiControllers;\n channelSnapshot.lockedControllers = channelObject.lockedControllers;\n channelSnapshot.customControllers = channelObject.customControllers;\n \n // vibrato data\n channelSnapshot.channelVibrato = channelObject.channelVibrato;\n channelSnapshot.lockVibrato = channelObject.lockGSNRPNParams;\n \n // tuning and transpose data\n channelSnapshot.channelTransposeKeyShift = channelObject.channelTransposeKeyShift;\n channelSnapshot.channelOctaveTuning = channelObject.channelOctaveTuning;\n \n // other data\n channelSnapshot.isMuted = channelObject.isMuted;\n channelSnapshot.velocityOverride = channelObject.velocityOverride;\n channelSnapshot.drumChannel = channelObject.drumChannel;\n return channelSnapshot;\n }\n \n /**\n * Applies the snapshot to the specified channel.\n * @param spessaSynthProcessor {SpessaSynthProcessor}\n * @param channelNumber {number}\n * @param channelSnapshot {ChannelSnapshot}\n */\n static applyChannelSnapshot(spessaSynthProcessor, channelNumber, channelSnapshot)\n {\n const channelObject = spessaSynthProcessor.midiAudioChannels[channelNumber];\n channelObject.muteChannel(channelSnapshot.isMuted);\n channelObject.setDrums(channelSnapshot.drumChannel);\n \n // restore controllers\n channelObject.midiControllers = channelSnapshot.midiControllers;\n channelObject.lockedControllers = channelSnapshot.lockedControllers;\n channelObject.customControllers = channelSnapshot.customControllers;\n channelObject.updateChannelTuning();\n \n // restore vibrato and transpose\n channelObject.channelVibrato = channelSnapshot.channelVibrato;\n channelObject.lockGSNRPNParams = channelSnapshot.lockVibrato;\n channelObject.channelTransposeKeyShift = channelSnapshot.channelTransposeKeyShift;\n channelObject.channelOctaveTuning = channelSnapshot.channelOctaveTuning;\n channelObject.velocityOverride = channelSnapshot.velocityOverride;\n \n // restore preset and lock\n channelObject.setPresetLock(false);\n channelObject.setBankSelect(channelSnapshot.bank, channelSnapshot.isBankLSB);\n channelObject.programChange(channelSnapshot.program);\n channelObject.setPresetLock(channelSnapshot.lockPreset);\n channelObject.lockedSystem = channelSnapshot.lockedSystem;\n }\n}", "import { SpessaSynthInfo } from \"../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../utils/other.js\";\nimport { ChannelSnapshot } from \"./channel_snapshot.js\";\nimport { masterParameterType } from \"../engine_methods/controller_control/master_parameters.js\";\n\n/**\n * Represents a snapshot of the synthesizer's state.\n */\nexport class SynthesizerSnapshot\n{\n /**\n * The individual channel snapshots.\n * @type {ChannelSnapshot[]}\n */\n channelSnapshots;\n \n /**\n * Key modifiers.\n * @type {KeyModifier[][]}\n */\n keyMappings;\n \n /**\n * Main synth volume (set by MIDI), from 0 to 1.\n * @type {number}\n */\n mainVolume;\n \n /**\n * Master stereo panning, from -1 to 1.\n * @type {number}\n */\n pan;\n \n /**\n * The synth's interpolation type.\n * @type {interpolationTypes}\n */\n interpolation;\n \n /**\n * The synth's system. Values can be \"gs\", \"gm\", \"gm2\" or \"xg\".\n * @type {SynthSystem}\n */\n system;\n \n /**\n * The current synth transposition in semitones. Can be a float.\n * @type {number}\n */\n transposition;\n \n \n /**\n * Creates a snapshot of the synthesizer's state.\n * @param spessaSynthProcessor {SpessaSynthProcessor}\n * @returns {SynthesizerSnapshot}\n */\n static createSynthesizerSnapshot(spessaSynthProcessor)\n {\n const snapshot = new SynthesizerSnapshot();\n // channel snapshots\n snapshot.channelSnapshots =\n spessaSynthProcessor.midiAudioChannels.map((_, i) =>\n ChannelSnapshot.getChannelSnapshot(spessaSynthProcessor, i));\n \n // key mappings\n snapshot.keyMappings = spessaSynthProcessor.keyModifierManager.getMappings();\n // pan and volume\n snapshot.mainVolume = spessaSynthProcessor.midiVolume;\n snapshot.pan = spessaSynthProcessor.pan;\n \n // others\n snapshot.system = spessaSynthProcessor.system;\n snapshot.interpolation = spessaSynthProcessor.interpolationType;\n snapshot.transposition = spessaSynthProcessor.transposition;\n \n // effect config is stored on the main thread, leave it empty\n snapshot.effectsConfig = {};\n return snapshot;\n \n }\n \n /**\n * Applies the snapshot to the synthesizer.\n * @param spessaSynthProcessor {SpessaSynthProcessor}\n * @param snapshot {SynthesizerSnapshot}\n */\n static applySnapshot(spessaSynthProcessor, snapshot)\n {\n // restore system\n spessaSynthProcessor.setSystem(snapshot.system);\n \n // restore pan and volume\n spessaSynthProcessor.setMasterParameter(masterParameterType.mainVolume, snapshot.mainVolume);\n spessaSynthProcessor.setMasterParameter(masterParameterType.masterPan, snapshot.pan);\n spessaSynthProcessor.transposeAllChannels(snapshot.transposition);\n spessaSynthProcessor.interpolationType = snapshot.interpolation;\n spessaSynthProcessor.keyModifierManager.setMappings(snapshot.keyMappings);\n \n // add channels if more needed\n while (spessaSynthProcessor.midiAudioChannels.length < snapshot.channelSnapshots.length)\n {\n spessaSynthProcessor.createMidiChannel();\n }\n \n // restore channels\n snapshot.channelSnapshots.forEach((channelSnapshot, index) =>\n {\n ChannelSnapshot.applyChannelSnapshot(spessaSynthProcessor, index, channelSnapshot);\n });\n \n SpessaSynthInfo(\"%cFinished restoring controllers!\", consoleColors.info);\n }\n}\n\n", "import { SpessaSynthInfo } from \"../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../utils/other.js\";\nimport { SynthesizerSnapshot } from \"./synthesizer_snapshot.js\";\n\n/**\n * Applies the snapshot to the synth\n * @param snapshot {SynthesizerSnapshot}\n * @this {SpessaSynthProcessor}\n */\nexport function applySynthesizerSnapshot(snapshot)\n{\n SynthesizerSnapshot.applySnapshot(this, snapshot);\n SpessaSynthInfo(\"%cFinished applying snapshot!\", consoleColors.info);\n this.resetAllControllers();\n}", "/**\n * lfo.js\n * purpose: low frequency triangel oscillator\n */\n\n/**\n * Calculates a triangular wave value for the given time\n * @param startTime {number} seconds\n * @param frequency {number} Hz\n * @param currentTime {number} seconds\n * @return {number} the value from -1 to 1\n */\nexport function getLFOValue(startTime, frequency, currentTime)\n{\n if (currentTime < startTime)\n {\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", "/**\n * wavetable_oscillator.js\n * purpose: plays back raw audio data at an arbitrary playback rate\n */\n\n\nexport class WavetableOscillator\n{\n \n /**\n * Fills the output buffer with raw sample data using linear interpolation\n * @param voice {Voice} the voice we're working on\n * @param outputBuffer {Float32Array} the output buffer to write to\n */\n static getSampleLinear(voice, outputBuffer)\n {\n const sample = voice.sample;\n let cur = sample.cursor;\n const sampleData = sample.sampleData;\n \n if (sample.isLooping)\n {\n const loopLength = sample.loopEnd - sample.loopStart;\n for (let i = 0; i < outputBuffer.length; i++)\n {\n // check for loop\n while (cur >= sample.loopEnd)\n {\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 {\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 += sample.playbackStep * voice.currentTuningCalculated;\n }\n }\n else\n {\n if (sample.loopingMode === 2 && !voice.isInRelease)\n {\n return;\n }\n for (let i = 0; i < outputBuffer.length; i++)\n {\n \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 {\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 += sample.playbackStep * voice.currentTuningCalculated;\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 {Voice} the voice we're working on\n * @param outputBuffer {Float32Array} the output buffer to write to\n */\n static getSampleNearest(voice, outputBuffer)\n {\n const sample = voice.sample;\n let cur = sample.cursor;\n const loopLength = sample.loopEnd - sample.loopStart;\n const sampleData = sample.sampleData;\n if (voice.sample.isLooping)\n {\n for (let i = 0; i < outputBuffer.length; i++)\n {\n // check for loop\n while (cur >= sample.loopEnd)\n {\n cur -= loopLength;\n }\n \n // grab the nearest neighbor\n let ceil = ~~cur + 1;\n \n while (ceil >= sample.loopEnd)\n {\n ceil -= loopLength;\n }\n \n outputBuffer[i] = sampleData[ceil];\n cur += sample.playbackStep * voice.currentTuningCalculated;\n }\n }\n else\n {\n if (sample.loopingMode === 2 && !voice.isInRelease)\n {\n return;\n }\n for (let i = 0; i < outputBuffer.length; i++)\n {\n \n // nearest neighbor\n const ceil = ~~cur + 1;\n \n // flag the voice as finished if needed\n if (ceil >= sample.end)\n {\n voice.finished = true;\n return;\n }\n \n //nearest neighbor (uncomment to use)\n outputBuffer[i] = sampleData[ceil];\n cur += sample.playbackStep * voice.currentTuningCalculated;\n }\n }\n sample.cursor = cur;\n }\n \n \n /**\n * Fills the output buffer with raw sample data using cubic interpolation\n * @param voice {Voice} the voice we're working on\n * @param outputBuffer {Float32Array} the output buffer to write to\n */\n static getSampleCubic(voice, outputBuffer)\n {\n const sample = voice.sample;\n let cur = sample.cursor;\n const sampleData = sample.sampleData;\n \n if (sample.isLooping)\n {\n const loopLength = sample.loopEnd - sample.loopStart;\n for (let i = 0; i < outputBuffer.length; i++)\n {\n // check for loop\n while (cur >= sample.loopEnd)\n {\n cur -= loopLength;\n }\n \n // math comes from\n // https://stackoverflow.com/questions/1125666/how-do-you-do-bicubic-or-other-non-linear-interpolation-of-re-sampled-audio-da\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 = y1 + 1; // point 1 after the cursor\n let y3 = y2 + 1; // point 2 after the cursor\n const t = cur - y0; // distance from y0 to cursor\n // y0 is not handled here\n // as it's math.floor of cur which is handled above\n if (y1 >= sample.loopEnd)\n {\n y1 -= loopLength;\n }\n if (y2 >= sample.loopEnd)\n {\n y2 -= loopLength;\n }\n if (y3 >= sample.loopEnd)\n {\n y3 -= loopLength;\n }\n \n // grab the samples\n const x0 = sampleData[y0];\n const x1 = sampleData[y1];\n const x2 = sampleData[y2];\n const x3 = sampleData[y3];\n \n // interpolate\n // const c0 = x1\n const c1 = 0.5 * (x2 - x0);\n const c2 = x0 - (2.5 * x1) + (2 * x2) - (0.5 * x3);\n const c3 = (0.5 * (x3 - x0)) + (1.5 * (x1 - x2));\n outputBuffer[i] = (((((c3 * t) + c2) * t) + c1) * t) + x1;\n \n \n cur += sample.playbackStep * voice.currentTuningCalculated;\n }\n }\n else\n {\n if (sample.loopingMode === 2 && !voice.isInRelease)\n {\n return;\n }\n for (let i = 0; i < outputBuffer.length; i++)\n {\n \n // math comes from\n // https://stackoverflow.com/questions/1125666/how-do-you-do-bicubic-or-other-non-linear-interpolation-of-re-sampled-audio-da\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 = y1 + 1; // point 1 after the cursor\n let y3 = y2 + 1; // point 2 after the cursor\n const t = cur - y0; // distance from y0 to cursor\n \n // flag as finished if needed\n if (y1 >= sample.end ||\n y2 >= sample.end ||\n y3 >= sample.end)\n {\n voice.finished = true;\n return;\n }\n \n // grab the samples\n const x0 = sampleData[y0];\n const x1 = sampleData[y1];\n const x2 = sampleData[y2];\n const x3 = sampleData[y3];\n \n // interpolate\n const c1 = 0.5 * (x2 - x0);\n const c2 = x0 - (2.5 * x1) + (2 * x2) - (0.5 * x3);\n const c3 = (0.5 * (x3 - x0)) + (1.5 * (x1 - x2));\n outputBuffer[i] = (((((c3 * t) + c2) * t) + c1) * t) + x1;\n \n cur += sample.playbackStep * voice.currentTuningCalculated;\n }\n }\n voice.sample.cursor = cur;\n }\n}", "import { VolumeEnvelope } from \"../engine_components/volume_envelope.js\";\nimport { ModulationEnvelope } from \"../engine_components/modulation_envelope.js\";\nimport { generatorTypes } from \"../../../soundfont/basic_soundfont/generator.js\";\nimport { customControllers } from \"../engine_components/controller_tables.js\";\nimport { absCentsToHz, timecentsToSeconds } from \"../engine_components/unit_converter.js\";\nimport { getLFOValue } from \"../engine_components/lfo.js\";\nimport { WavetableOscillator } from \"../engine_components/wavetable_oscillator.js\";\nimport { LowpassFilter } from \"../engine_components/lowpass_filter.js\";\nimport { interpolationTypes } from \"../engine_components/enums.js\";\n\n/**\n * Renders a voice to the stereo output buffer\n * @param voice {Voice} the voice to render\n * @param timeNow {number} current time in seconds\n * @param outputLeft {Float32Array} the left output buffer\n * @param outputRight {Float32Array} the right output buffer\n * @param reverbOutputLeft {Float32Array} left output for reverb\n * @param reverbOutputRight {Float32Array} right output for reverb\n * @param chorusOutputLeft {Float32Array} left output for chorus\n * @param chorusOutputRight {Float32Array} right output for chorus\n * @this {MidiAudioChannel}\n * @returns {boolean} true if the voice is finished\n */\nexport function renderVoice(\n voice, timeNow,\n outputLeft, outputRight,\n reverbOutputLeft, reverbOutputRight,\n chorusOutputLeft, chorusOutputRight\n)\n{\n // check if release\n if (!voice.isInRelease)\n {\n // if not in release, check if the release time is\n if (timeNow >= voice.releaseStartTime)\n {\n // release the voice here\n voice.isInRelease = true;\n VolumeEnvelope.startRelease(voice);\n ModulationEnvelope.startRelease(voice);\n if (voice.sample.loopingMode === 3)\n {\n voice.sample.isLooping = false;\n }\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 {\n if (voice.isInRelease)\n {\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 = 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 = this.synth.tunings[this.preset.program]?.[voice.realKey];\n if (tuning !== undefined && tuning?.midiNote >= 0)\n {\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 {\n // 0 to 1\n const elapsed = Math.min((timeNow - voice.startTime) / voice.portamentoDuration, 1);\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 += (targetKey - voice.sample.rootKey) * voice.modulatedGenerators[generatorTypes.scaleTuning];\n \n // vibrato LFO\n const vibratoDepth = voice.modulatedGenerators[generatorTypes.vibLfoToPitch];\n if (vibratoDepth !== 0)\n {\n // calculate start time and lfo value\n const vibStart = voice.startTime + timecentsToSeconds(voice.modulatedGenerators[generatorTypes.delayVibLFO]);\n const vibFreqHz = absCentsToHz(voice.modulatedGenerators[generatorTypes.freqVibLFO]);\n const lfoVal = getLFOValue(vibStart, vibFreqHz, timeNow);\n // use modulation multiplier (RPN modulation depth)\n cents += lfoVal * (vibratoDepth * this.customControllers[customControllers.modulationMultiplier]);\n }\n \n // low pass excursion with LFO and mod envelope\n let lowpassExcursion = 0;\n \n // mod LFO\n const modPitchDepth = voice.modulatedGenerators[generatorTypes.modLfoToPitch];\n const modVolDepth = voice.modulatedGenerators[generatorTypes.modLfoToVolume];\n const modFilterDepth = voice.modulatedGenerators[generatorTypes.modLfoToFilterFc];\n let modLfoCentibels = 0;\n // don't compute mod lfo unless necessary\n if (modPitchDepth !== 0 || modFilterDepth !== 0 || modVolDepth !== 0)\n {\n // calculate start time and lfo value\n const modStart = voice.startTime + timecentsToSeconds(voice.modulatedGenerators[generatorTypes.delayModLFO]);\n const modFreqHz = absCentsToHz(voice.modulatedGenerators[generatorTypes.freqModLFO]);\n const modLfoValue = getLFOValue(modStart, modFreqHz, timeNow);\n // use modulation multiplier (RPN modulation depth)\n cents += modLfoValue * (modPitchDepth * this.customControllers[customControllers.modulationMultiplier]);\n // vole nv volume offset\n // negate the lfo value because audigy starts with increase rather than decrease\n modLfoCentibels = -modLfoValue * modVolDepth;\n // low pass frequency\n lowpassExcursion += modLfoValue * modFilterDepth;\n }\n \n // channel vibrato (GS NRPN)\n if (this.channelVibrato.depth > 0)\n {\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 {\n cents += channelVibrato * this.channelVibrato.depth;\n }\n }\n \n // mod env\n const modEnvPitchDepth = voice.modulatedGenerators[generatorTypes.modEnvToPitch];\n const modEnvFilterDepth = voice.modulatedGenerators[generatorTypes.modEnvToFilterFc];\n // don't compute mod env unless necessary\n if (modEnvFilterDepth !== 0 || modEnvPitchDepth !== 0)\n {\n const modEnv = ModulationEnvelope.getValue(voice, timeNow);\n // apply values\n lowpassExcursion += modEnv * modEnvFilterDepth;\n cents += modEnv * modEnvPitchDepth;\n }\n \n // finally, calculate the playback rate\n const centsTotal = ~~(cents + semitones * 100);\n if (centsTotal !== voice.currentTuningCents)\n {\n voice.currentTuningCents = centsTotal;\n voice.currentTuningCalculated = Math.pow(2, centsTotal / 1200);\n }\n \n \n // SYNTHESIS\n const bufferOut = new Float32Array(outputLeft.length);\n \n // wave table oscillator\n switch (this.synth.interpolationType)\n {\n case interpolationTypes.fourthOrder:\n WavetableOscillator.getSampleCubic(voice, bufferOut);\n break;\n \n case interpolationTypes.linear:\n default:\n WavetableOscillator.getSampleLinear(voice, bufferOut);\n break;\n \n case interpolationTypes.nearestNeighbor:\n WavetableOscillator.getSampleNearest(voice, bufferOut);\n break;\n }\n \n // low pass filter\n LowpassFilter.apply(voice, bufferOut, lowpassExcursion, this.synth.filterSmoothingFactor);\n \n // vol env\n VolumeEnvelope.apply(voice, bufferOut, modLfoCentibels, this.synth.volumeEnvelopeSmoothingFactor);\n \n this.panVoice(\n voice,\n bufferOut,\n outputLeft, outputRight,\n reverbOutputLeft, reverbOutputRight,\n chorusOutputLeft, chorusOutputRight\n );\n return voice.finished;\n}", "import { generatorTypes } from \"../../../../soundfont/basic_soundfont/generator.js\";\n\n/**\n * Stops a note nearly instantly\n * @param midiNote {number}\n * @param releaseTime {number} ticks\n * @this {MidiAudioChannel}\n */\nexport function killNote(midiNote, releaseTime = -12000)\n{\n this.voices.forEach(v =>\n {\n if (v.realKey !== midiNote)\n {\n return;\n }\n v.modulatedGenerators[generatorTypes.releaseVolEnv] = releaseTime; // set release to be very short\n v.release(this.synth.currentSynthTime);\n });\n}", "import { customControllers } from \"../../engine_components/controller_tables.js\";\nimport { SpessaSynthInfo } from \"../../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../../utils/other.js\";\n\n/**\n * Sets the channel's tuning\n * @this {MidiAudioChannel}\n * @param cents {number}\n * @param log {boolean}\n */\nexport function setTuning(cents, log = true)\n{\n cents = Math.round(cents);\n this.setCustomController(customControllers.channelTuning, cents);\n if (!log)\n {\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}", "import { SpessaSynthInfo } from \"../../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../../utils/other.js\";\nimport { customControllers } from \"../../engine_components/controller_tables.js\";\n\n/**\n * @this {MidiAudioChannel}\n * @param cents {number}\n */\nexport function setModulationDepth(cents)\n{\n cents = Math.round(cents);\n SpessaSynthInfo(\n `%cChannel ${this.channelNumber} modulation depth. Cents: %c${cents}`,\n consoleColors.info,\n consoleColors.value\n );\n /* ==============\n IMPORTANT\n here we convert cents into a multiplier.\n midi spec assumes the default is 50 cents,\n but it might be different for the soundfont,\n so we create a multiplier by dividing cents by 50.\n for example, if we want 100 cents, then multiplier will be 2,\n which for a preset with depth of 50 will create 100.\n ================ */\n this.setCustomController(customControllers.modulationMultiplier, cents / 50);\n}", "import { consoleColors } from \"../../../../utils/other.js\";\nimport { SpessaSynthInfo } from \"../../../../utils/loggin.js\";\nimport { modulatorSources } from \"../../../../soundfont/basic_soundfont/modulator.js\";\nimport { customControllers, dataEntryStates, NON_CC_INDEX_OFFSET } from \"../../engine_components/controller_tables.js\";\nimport { midiControllers } from \"../../../../midi/midi_message.js\";\n\n/**\n * Executes a data entry for an RPN tuning\n * @param dataValue {number} dataEntry LSB\n * @this {MidiAudioChannel}\n * @private\n */\nexport function dataEntryFine(dataValue)\n{\n switch (this.dataEntryState)\n {\n default:\n break;\n \n case dataEntryStates.RPCoarse:\n case dataEntryStates.RPFine:\n const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);\n switch (rpnValue)\n {\n default:\n break;\n \n // pitch bend range fine tune\n case 0x0000:\n if (dataValue === 0)\n {\n break;\n }\n // 14-bit value, so upper 7 are coarse and lower 7 are fine!\n this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] |= dataValue;\n const actualTune = (this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] >> 7) + dataValue / 128;\n SpessaSynthInfo(\n `%cChannel ${this.channelNumber} bend range. Semitones: %c${actualTune}`,\n consoleColors.info,\n consoleColors.value\n );\n break;\n \n // fine-tuning\n case 0x0001:\n // grab the data and shift\n const coarse = 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 // modulation depth\n case 0x0005:\n const currentModulationDepthCents = this.customControllers[customControllers.modulationMultiplier] * 50;\n let cents = currentModulationDepthCents + (dataValue / 128) * 100;\n this.setModulationDepth(cents);\n break;\n \n case 0x3FFF:\n this.resetParameters();\n break;\n \n }\n \n }\n}", "import { getModulatorCurveValue, MOD_PRECOMPUTED_LENGTH } from \"./modulator_curves.js\";\nimport { VolumeEnvelope } from \"./volume_envelope.js\";\nimport { ModulationEnvelope } from \"./modulation_envelope.js\";\nimport { generatorLimits, generatorTypes } from \"../../../soundfont/basic_soundfont/generator.js\";\nimport { Modulator, modulatorSources } from \"../../../soundfont/basic_soundfont/modulator.js\";\nimport { NON_CC_INDEX_OFFSET } from \"./controller_tables.js\";\n\n/**\n * compute_modulator.js\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 {Int16Array} all midi controllers as 14bit values + the non-controller indexes, starting at 128\n * @param modulator {Modulator} the modulator to compute\n * @param voice {Voice} the voice belonging to the modulator\n * @returns {number} the computed value\n */\nexport function computeModulator(controllerTable, modulator, voice)\n{\n if (modulator.transformAmount === 0)\n {\n modulator.currentValue = 0;\n return 0;\n }\n // mapped to 0-16384\n let rawSourceValue;\n if (modulator.sourceUsesCC)\n {\n rawSourceValue = controllerTable[modulator.sourceIndex];\n }\n else\n {\n const index = modulator.sourceIndex + NON_CC_INDEX_OFFSET;\n switch (modulator.sourceIndex)\n {\n case modulatorSources.noController:\n rawSourceValue = 16383; // equals to 1\n break;\n \n case modulatorSources.noteOnKeyNum:\n rawSourceValue = voice.midiNote << 7;\n break;\n \n case modulatorSources.noteOnVelocity:\n rawSourceValue = voice.velocity << 7;\n break;\n \n case modulatorSources.polyPressure:\n rawSourceValue = voice.pressure << 7;\n break;\n \n default:\n rawSourceValue = controllerTable[index]; // pitch bend and range are stored in the cc table\n break;\n }\n \n }\n \n const sourceValue = transforms[modulator.sourceCurveType][modulator.sourcePolarity][modulator.sourceDirection][rawSourceValue];\n \n // mapped to 0-127\n let rawSecondSrcValue;\n if (modulator.secSrcUsesCC)\n {\n rawSecondSrcValue = controllerTable[modulator.secSrcIndex];\n }\n else\n {\n const index = modulator.secSrcIndex + NON_CC_INDEX_OFFSET;\n switch (modulator.secSrcIndex)\n {\n case modulatorSources.noController:\n rawSecondSrcValue = 16383; // equals to 1\n break;\n \n case modulatorSources.noteOnKeyNum:\n rawSecondSrcValue = voice.midiNote << 7;\n break;\n \n case modulatorSources.noteOnVelocity:\n rawSecondSrcValue = voice.velocity << 7;\n break;\n \n case modulatorSources.polyPressure:\n rawSecondSrcValue = voice.pressure << 7;\n break;\n \n default:\n rawSecondSrcValue = controllerTable[index]; // pitch bend and range are stored in the cc table\n }\n \n }\n const secondSrcValue = transforms[modulator.secSrcCurveType][modulator.secSrcPolarity][modulator.secSrcDirection][rawSecondSrcValue];\n \n // see the comment for isEffectModulator (modulator.js in basic_soundfont) for explanation\n let transformAmount = modulator.transformAmount;\n if (modulator.isEffectModulator && transformAmount <= 1000)\n {\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 {\n // abs value\n computedValue = Math.abs(computedValue);\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 {Voice} the voice to compute modulators for\n * @param controllerTable {Int16Array} all midi controllers as 14bit values + the non-controller indexes, starting at 128\n * @param sourceUsesCC {number} what modulators should be computed, -1 means all, 0 means modulator source enum 1 means midi controller\n * @param sourceIndex {number} enum for the source\n */\nexport function computeModulators(voice, controllerTable, sourceUsesCC = -1, sourceIndex = 0)\n{\n const modulators = voice.modulators;\n const generators = voice.generators;\n const modulatedGenerators = voice.modulatedGenerators;\n \n if (sourceUsesCC === -1)\n {\n // All modulators mode: compute all modulators\n modulatedGenerators.set(generators);\n modulators.forEach(mod =>\n {\n const limits = generatorLimits[mod.modulatorDestination];\n const newValue = modulatedGenerators[mod.modulatorDestination] + computeModulator(\n controllerTable,\n mod,\n voice\n );\n modulatedGenerators[mod.modulatorDestination] = Math.max(\n limits.min,\n Math.min(newValue, limits.max)\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 volenvNeedsRecalculation = new Set([\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();\n \n modulators.forEach(mod =>\n {\n if (\n (mod.sourceUsesCC === sourceUsesCC && mod.sourceIndex === sourceIndex) ||\n (mod.secSrcUsesCC === sourceUsesCC && mod.secSrcIndex === sourceIndex)\n )\n {\n const destination = mod.modulatorDestination;\n if (!computedDestinations.has(destination))\n {\n // Reset this destination\n modulatedGenerators[destination] = generators[destination];\n // compute our modulator\n computeModulator(controllerTable, mod, voice);\n // sum the values of all modulators for this destination\n modulators.forEach(m =>\n {\n if (m.modulatorDestination === destination)\n {\n const limits = generatorLimits[mod.modulatorDestination];\n const newValue = modulatedGenerators[mod.modulatorDestination] + m.currentValue;\n modulatedGenerators[mod.modulatorDestination] = Math.max(\n limits.min,\n Math.min(newValue, limits.max)\n );\n }\n });\n computedDestinations.add(destination);\n }\n }\n });\n \n // Recalculate volume envelope if necessary\n if ([...computedDestinations].some(dest => volenvNeedsRecalculation.has(dest)))\n {\n VolumeEnvelope.recalculate(voice);\n }\n \n ModulationEnvelope.recalculate(voice);\n}\n\n\n/**\n * as follows: transforms[curveType][polarity][direction] is an array\n * @type {Float32Array[][][]}\n */\nconst transforms = [];\n\nfor (let curve = 0; curve < 4; curve++)\n{\n transforms[curve] =\n [\n [\n new Float32Array(MOD_PRECOMPUTED_LENGTH),\n new Float32Array(MOD_PRECOMPUTED_LENGTH)\n ],\n [\n new Float32Array(MOD_PRECOMPUTED_LENGTH),\n new Float32Array(MOD_PRECOMPUTED_LENGTH)\n ]\n ];\n for (let i = 0; i < MOD_PRECOMPUTED_LENGTH; i++)\n {\n \n // polarity 0 dir 0\n transforms[curve][0][0][i] = getModulatorCurveValue(\n 0,\n curve,\n i / MOD_PRECOMPUTED_LENGTH,\n 0\n );\n \n // polarity 1 dir 0\n transforms[curve][1][0][i] = getModulatorCurveValue(\n 0,\n curve,\n i / MOD_PRECOMPUTED_LENGTH,\n 1\n );\n \n // polarity 0 dir 1\n transforms[curve][0][1][i] = getModulatorCurveValue(\n 1,\n curve,\n i / MOD_PRECOMPUTED_LENGTH,\n 0\n );\n \n // polarity 1 dir 1\n transforms[curve][1][1][i] = getModulatorCurveValue(\n 1,\n curve,\n i / MOD_PRECOMPUTED_LENGTH,\n 1\n );\n }\n}", "import { midiControllers } from \"../../../../midi/midi_message.js\";\nimport { computeModulators } from \"../../engine_components/compute_modulator.js\";\nimport { channelConfiguration, dataEntryStates } from \"../../engine_components/controller_tables.js\";\n\n/**\n * @param controllerNumber {number}\n * @param controllerValue {number}\n * @param force {boolean}\n * @this {MidiAudioChannel}\n */\nexport function controllerChange(controllerNumber, controllerValue, force = false)\n{\n if (controllerNumber > 127)\n {\n // channel configuration. force must be set to true\n if (!force)\n {\n return;\n }\n switch (controllerNumber)\n {\n default:\n return;\n \n case channelConfiguration.velocityOverride:\n this.velocityOverride = controllerValue;\n }\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.lsbForControl1ModulationWheel\n && controllerNumber <= midiControllers.lsbForControl13EffectControl2\n && controllerNumber !== midiControllers.lsbForControl6DataEntry\n )\n {\n const actualCCNum = controllerNumber - 32;\n if (this.lockedControllers[actualCCNum])\n {\n return;\n }\n // append the lower nibble to the main controller\n this.midiControllers[actualCCNum] = (this.midiControllers[actualCCNum] & 0x3F80) | (controllerValue & 0x7F);\n this.voices.forEach(v => computeModulators(v, this.midiControllers, 1, actualCCNum));\n }\n if (this.lockedControllers[controllerNumber])\n {\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 {\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.setBankSelect(controllerValue);\n break;\n \n case midiControllers.lsbForControl0BankSelect:\n this.setBankSelect(controllerValue, true);\n break;\n \n // check for RPN and NPRN and data entry\n case midiControllers.RPNLsb:\n this.dataEntryState = dataEntryStates.RPFine;\n break;\n \n case midiControllers.RPNMsb:\n this.dataEntryState = dataEntryStates.RPCoarse;\n break;\n \n case midiControllers.NRPNMsb:\n this.dataEntryState = dataEntryStates.NRPCoarse;\n break;\n \n case midiControllers.NRPNLsb:\n this.dataEntryState = dataEntryStates.NRPFine;\n break;\n \n case midiControllers.dataEntryMsb:\n this.dataEntryCoarse(controllerValue);\n break;\n \n case midiControllers.lsbForControl6DataEntry:\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 {\n this.holdPedal = true;\n }\n else\n {\n this.holdPedal = false;\n this.sustainedVoices.forEach(v =>\n {\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 => computeModulators(v, this.midiControllers, 1, controllerNumber));\n break;\n }\n }\n this.synth.callEvent(\"controllerchange\", {\n channel: this.channelNumber,\n controllerNumber: controllerNumber,\n controllerValue: controllerValue\n });\n}", "/**\n * stops all notes on a given channel\n * @param force {boolean}\n * @this {MidiAudioChannel}\n */\nexport function stopAllNotes(force = false)\n{\n if (force)\n {\n // force stop all\n this.voices.length = 0;\n this.sustainedVoices.length = 0;\n this.sendChannelProperty();\n }\n else\n {\n this.voices.forEach(v =>\n {\n if (v.isInRelease)\n {\n return;\n }\n v.release(this.synth.currentSynthTime);\n });\n this.sustainedVoices.forEach(v =>\n {\n v.release(this.synth.currentSynthTime);\n });\n }\n}", "/**\n * @param isMuted {boolean}\n * @this {MidiAudioChannel}\n */\nexport function muteChannel(isMuted)\n{\n if (isMuted)\n {\n this.stopAllNotes(true);\n }\n this.isMuted = isMuted;\n this.sendChannelProperty();\n this.synth.callEvent(\"mutechannel\", {\n channel: this.channelNumber,\n isMuted: isMuted\n });\n}", "import { customControllers } from \"../../engine_components/controller_tables.js\";\nimport { midiControllers } from \"../../../../midi/midi_message.js\";\n\n/**\n * Transposes the channel by given amount of semitones\n * @this {MidiAudioChannel}\n * @param semitones {number} Can be float\n * @param force {boolean} defaults to false, if true transposes the channel even if it's a drum channel\n */\nexport function transposeChannel(semitones, force = false)\n{\n if (!this.drumChannel)\n {\n semitones += this.synth.transposition;\n }\n const keyShift = Math.trunc(semitones);\n const currentTranspose = this.channelTransposeKeyShift + this.customControllers[customControllers.channelTransposeFine] / 100;\n if (\n (this.drumChannel && !force)\n || semitones === currentTranspose\n )\n {\n return;\n }\n if (keyShift !== this.channelTransposeKeyShift)\n {\n // stop all (and emit cc change)\n this.controllerChange(midiControllers.allNotesOff, 127);\n }\n // apply transpose\n this.channelTransposeKeyShift = keyShift;\n this.setCustomController(customControllers.channelTransposeFine, (semitones - keyShift) * 100);\n this.sendChannelProperty();\n}", "import { customControllers, dataEntryStates, NON_CC_INDEX_OFFSET } from \"../../engine_components/controller_tables.js\";\nimport { SpessaSynthInfo, SpessaSynthWarn } from \"../../../../utils/loggin.js\";\nimport { consoleColors } from \"../../../../utils/other.js\";\nimport { midiControllers } from \"../../../../midi/midi_message.js\";\nimport { modulatorSources } from \"../../../../soundfont/basic_soundfont/modulator.js\";\n\n\n/**\n * @enum {number}\n */\nconst registeredParameterTypes = {\n pitchBendRange: 0x0000,\n fineTuning: 0x0001,\n coarseTuning: 0x0002,\n modulationDepth: 0x0005,\n resetParameters: 0x3FFF\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 nonRegisteredParameterNumbers = {\n partParameter: 0x01,\n \n vibratoRate: 0x08,\n vibratoDepth: 0x09,\n vibratoDelay: 0x0A,\n \n EGAttackTime: 0x64,\n EGReleaseTime: 0x66,\n \n TVFFilterCutoff: 0x20,\n drumReverb: 0x1D\n};\n\n\n/**\n * Executes a data entry for an NRP for a sc88pro NRP (because touhou yes) and RPN tuning\n * @param dataValue {number} dataEntryCoarse MSB\n * @this {MidiAudioChannel}\n * @private\n */\nexport function dataEntryCoarse(dataValue)\n{\n const addDefaultVibrato = () =>\n {\n if (this.channelVibrato.delay === 0 && this.channelVibrato.rate === 0 && 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 const coolInfo = (what, value, type) =>\n {\n if (type.length > 0)\n {\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 {\n default:\n case dataEntryStates.Idle:\n break;\n \n // process GS NRPNs\n case dataEntryStates.NRPFine:\n if (this.lockGSNRPNParams)\n {\n return;\n }\n /**\n * @type {number}\n */\n const NRPNCoarse = this.midiControllers[midiControllers.NRPNMsb] >> 7;\n /**\n * @type {number}\n */\n const NRPNFine = this.midiControllers[midiControllers.NRPNLsb] >> 7;\n switch (NRPNCoarse)\n {\n default:\n if (dataValue === 64)\n {\n // default value\n return;\n }\n SpessaSynthWarn(\n `%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNFine.toString(16)\n .toUpperCase()} 0x${NRPNFine.toString(\n 16).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 nonRegisteredParameterNumbers.partParameter:\n switch (NRPNFine)\n {\n default:\n if (dataValue === 64)\n {\n // default value\n return;\n }\n SpessaSynthWarn(\n `%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNCoarse.toString(16)} 0x${NRPNFine.toString(\n 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 // vibrato rate\n case nonRegisteredParameterNumbers.vibratoRate:\n if (dataValue === 64)\n {\n return;\n }\n addDefaultVibrato();\n this.channelVibrato.rate = (dataValue / 64) * 8;\n coolInfo(\"Vibrato rate\", `${dataValue} = ${this.channelVibrato.rate}`, \"Hz\");\n break;\n \n // vibrato depth\n case nonRegisteredParameterNumbers.vibratoDepth:\n if (dataValue === 64)\n {\n return;\n }\n addDefaultVibrato();\n this.channelVibrato.depth = dataValue / 2;\n coolInfo(\"Vibrato depth\", `${dataValue} = ${this.channelVibrato.depth}`, \"cents of detune\");\n break;\n \n // vibrato delay\n case nonRegisteredParameterNumbers.vibratoDelay:\n if (dataValue === 64)\n {\n return;\n }\n addDefaultVibrato();\n this.channelVibrato.delay = (dataValue / 64) / 3;\n coolInfo(\"Vibrato delay\", `${dataValue} = ${this.channelVibrato.delay}`, \"seconds\");\n break;\n \n // filter cutoff\n case nonRegisteredParameterNumbers.TVFFilterCutoff:\n // affect the \"brightness\" controller as we have a default modulator that controls it\n this.controllerChange(midiControllers.brightness, dataValue);\n coolInfo(\"Filter cutoff\", dataValue.toString(), \"\");\n break;\n \n // attack time\n case nonRegisteredParameterNumbers.EGAttackTime:\n // affect the \"attack time\" controller as we have a default modulator that controls it\n this.controllerChange(midiControllers.attackTime, dataValue);\n coolInfo(\"EG attack time\", dataValue.toString(), \"\");\n break;\n \n // release time\n case nonRegisteredParameterNumbers.EGReleaseTime:\n // affect the \"release time\" controller as we have a default modulator that controls it\n this.controllerChange(midiControllers.releaseTime, dataValue);\n coolInfo(\"EG release time\", dataValue.toString(), \"\");\n break;\n }\n break;\n \n // drum reverb\n case nonRegisteredParameterNumbers.drumReverb:\n const reverb = dataValue;\n this.controllerChange(midiControllers.reverbDepth, reverb);\n coolInfo(\"GS Drum reverb\", reverb.toString(), \"percent\");\n break;\n }\n break;\n \n case dataEntryStates.RPCoarse:\n case dataEntryStates.RPFine:\n /**\n * @type {number}\n */\n const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);\n switch (rpnValue)\n {\n default:\n SpessaSynthWarn(\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.pitchBendRange:\n this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] = dataValue << 7;\n coolInfo(\"Pitch bend range\", dataValue.toString(), \"semitones\");\n break;\n \n // coarse tuning\n case registeredParameterTypes.coarseTuning:\n // semitones\n const semitones = dataValue - 64;\n this.setCustomController(customControllers.channelTuningSemitones, semitones);\n coolInfo(\"Coarse tuning\", semitones.toString(), \"semitones\");\n break;\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}", "// 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 = {\n 0: 0.000,\n 1: 0.006,\n 2: 0.023,\n 4: 0.050,\n 8: 0.110,\n 16: 0.250,\n 32: 0.500,\n 64: 2.060,\n 80: 4.200,\n 96: 8.400,\n 112: 19.500,\n 116: 26.700,\n 120: 40.000,\n 124: 80.000,\n 127: 480.000\n};\n\n/**\n * @param value {number}\n * @returns {number}\n */\nfunction getLookup(value)\n{\n if (portamentoLookup[value] !== undefined)\n {\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 (let key of Object.keys(portamentoLookup))\n {\n key = parseInt(key);\n if (key < value && (lower === null || key > lower))\n {\n lower = key;\n }\n if (key > value && (upper === null || key < upper))\n {\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 {\n let lowerTime = portamentoLookup[lower];\n let upperTime = portamentoLookup[upper];\n \n // linear interpolation\n return lowerTime + ((value - lower) * (upperTime - lowerTime)) / (upper - lower);\n }\n return 0;\n}\n\n\n/**\n * Converts portamento time to seconds\n * @param time {number} 0 - 127\n * @param distance {number} distance in keys\n * @returns {number} seconds\n */\nexport function portamentoTimeToSeconds(time, distance)\n{\n // this seems to work fine for the MIDIs I have\n return getLookup(time) * (distance / 30);\n}", "import { computeModulators } from \"../engine_components/compute_modulator.js\";\nimport { generatorTypes } from \"../../../soundfont/basic_soundfont/generator.js\";\nimport { midiControllers } from \"../../../midi/midi_message.js\";\nimport { portamentoTimeToSeconds } from \"./portamento_time.js\";\n\n/**\n * sends a \"MIDI Note on message\"\n * @param midiNote {number}\n * @param velocity {number}\n * @this {MidiAudioChannel}\n */\nexport function noteOn(midiNote, velocity)\n{\n if (velocity < 1)\n {\n this.noteOff(midiNote);\n return;\n }\n velocity = Math.min(127, velocity);\n \n if (\n (this.synth.highPerformanceMode && this.synth.totalVoicesAmount > 200 && velocity < 40) ||\n (this.synth.highPerformanceMode && velocity < 10) ||\n (this.isMuted)\n )\n {\n return;\n }\n \n const realKey = midiNote + this.channelTransposeKeyShift;\n let sentMidiNote = realKey;\n \n if (realKey > 127 || realKey < 0)\n {\n return;\n }\n const program = this.preset.program;\n const tune = this.synth.tunings[program]?.[realKey]?.midiNote;\n if (tune >= 0)\n {\n sentMidiNote = tune;\n }\n \n // velocity override\n if (this.velocityOverride > 0)\n {\n velocity = this.velocityOverride;\n }\n \n // key velocity override\n const keyVel = this.synth.keyModifierManager.getVelocity(this.channelNumber, realKey);\n if (keyVel > -1)\n {\n velocity = keyVel;\n }\n \n // gain\n const voiceGain = this.synth.keyModifierManager.getGain(this.channelNumber, realKey);\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 = 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 !== sentMidiNote && // 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 {\n // a value of one means the initial portamento\n if (control !== 1)\n {\n const diff = Math.abs(sentMidiNote - currentFromKey);\n portamentoDuration = portamentoTimeToSeconds(portamentoTime, diff);\n portamentoFromKey = currentFromKey;\n }\n // set portamento control to previous value\n this.controllerChange(midiControllers.portamentoControl, sentMidiNote);\n }\n \n // get voices\n const voices = this.synth.getVoices(\n this.channelNumber,\n sentMidiNote,\n velocity,\n realKey\n );\n \n // zero means disabled\n let panOverride = 0;\n if (this.randomPan)\n {\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 {\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 // apply exclusive class\n const exclusive = voice.exclusiveClass;\n if (exclusive !== 0)\n {\n // kill all voices with the same exclusive class\n channelVoices.forEach(v =>\n {\n if (v.exclusiveClass === exclusive)\n {\n v.exclusiveRelease(this.synth.currentSynthTime);\n }\n });\n }\n // compute all modulators\n computeModulators(voice, this.midiControllers);\n // modulate sample offsets (these are not real time)\n const cursorStartOffset = voice.modulatedGenerators[generatorTypes.startAddrsOffset] + voice.modulatedGenerators[generatorTypes.startAddrsCoarseOffset] * 32768;\n const endOffset = voice.modulatedGenerators[generatorTypes.endAddrOffset] + voice.modulatedGenerators[generatorTypes.endAddrsCoarseOffset] * 32768;\n const loopStartOffset = voice.modulatedGenerators[generatorTypes.startloopAddrsOffset] + voice.modulatedGenerators[generatorTypes.startloopAddrsCoarseOffset] * 32768;\n const loopEndOffset = voice.modulatedGenerators[generatorTypes.endloopAddrsOffset] + voice.modulatedGenerators[generatorTypes.endloopAddrsCoarseOffset] * 32768;\n const sm = voice.sample;\n // apply them\n const clamp = num => 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 {\n const temp = sm.loopStart;\n sm.loopStart = sm.loopEnd;\n sm.loopEnd = temp;\n }\n if (sm.loopEnd - sm.loopStart < 1)\n {\n sm.loopingMode = 0;\n sm.isLooping = false;\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 = voice.volumeEnvelope.attenuationTargetGain;\n // set initial pan to avoid split second changing from middle to the correct value\n voice.currentPan = Math.max(-500, Math.min(500, voice.modulatedGenerators[generatorTypes.pan])); // -500 to 500\n });\n \n this.synth.totalVoicesAmount += voices.length;\n // cap the voices\n if (this.synth.totalVoicesAmount > this.synth.voiceCap)\n {\n this.synth.voiceKilling(voices.length);\n }\n channelVoices.push(...voices);\n this.sendChannelProperty();\n this.synth.callEvent(\"noteon\", {\n midiNote: midiNote,\n channel: this.channelNumber,\n velocity: velocity\n });\n \n}", "import { SpessaSynthWarn } from \"../../../../utils/loggin.js\";\n\n/**\n * Release a note\n * @param midiNote {number}\n * @this {MidiAudioChannel}\n */\nexport function noteOff(midiNote)\n{\n if (midiNote > 127 || midiNote < 0)\n {\n SpessaSynthWarn(`Received a noteOn for note`, midiNote, \"Ignoring.\");\n return;\n }\n \n let realKey = midiNote + this.channelTransposeKeyShift;\n \n // if high performance mode, kill notes instead of stopping them\n if (this.synth.highPerformanceMode)\n {\n // if the channel is percussion channel, do not kill the notes\n if (!this.drumChannel)\n {\n this.killNote(realKey, -6950);\n this.synth.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 {\n if (v.realKey !== realKey || v.isInRelease === true)\n {\n return;\n }\n // if hold pedal, move to sustain\n if (this.holdPedal)\n {\n this.sustainedVoices.push(v);\n }\n else\n {\n v.release(this.synth.currentSynthTime);\n }\n });\n this.synth.callEvent(\"noteoff\", {\n midiNote: midiNote,\n channel: this.channelNumber\n });\n}\n\n", "import { computeModulators } from \"../../engine_components/compute_modulator.js\";\nimport { modulatorSources } from \"../../../../soundfont/basic_soundfont/modulator.js\";\n\n/**\n * Sets the pressure of the given note on a specific channel\n * @this {MidiAudioChannel}\n * @param midiNote {number} 0-127\n * @param pressure {number} the pressure of the note\n */\nexport function polyPressure(midiNote, pressure)\n{\n this.voices.forEach(v =>\n {\n if (v.midiNote !== midiNote)\n {\n return;\n }\n v.pressure = pressure;\n computeModulators(\n v,\n this.midiControllers,\n 0,\n modulatorSources.polyPressure\n );\n });\n this.synth.callEvent(\"polypressure\", {\n channel: this.channelNumber,\n midiNote: midiNote,\n pressure: pressure\n });\n}", "import { NON_CC_INDEX_OFFSET } from \"../../engine_components/controller_tables.js\";\nimport { modulatorSources } from \"../../../../soundfont/basic_soundfont/modulator.js\";\nimport { computeModulators } from \"../../engine_components/compute_modulator.js\";\n\n/**\n * Sets the pressure of the given channel\n * @this {MidiAudioChannel}\n * @param pressure {number} the pressure of the channel\n */\nexport function channelPressure(pressure)\n{\n this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.channelPressure] = pressure << 7;\n this.voices.forEach(v =>\n computeModulators(\n v,\n this.midiControllers,\n 0,\n modulatorSources.channelPressure\n ));\n this.synth.callEvent(\"channelpressure\", {\n channel: this.channelNumber,\n pressure: pressure\n });\n}", "import { NON_CC_INDEX_OFFSET } from \"../../engine_components/controller_tables.js\";\nimport { modulatorSources } from \"../../../../soundfont/basic_soundfont/modulator.js\";\nimport { computeModulators } from \"../../engine_components/compute_modulator.js\";\n\n/**\n * Sets the pitch of the given channel\n * @this {MidiAudioChannel}\n * @param MSB {number} SECOND byte of the MIDI pitchWheel message\n * @param LSB {number} FIRST byte of the MIDI pitchWheel message\n */\nexport function pitchWheel(MSB, LSB)\n{\n if (this.lockedControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel])\n {\n return;\n }\n const bend = (LSB | (MSB << 7));\n this.synth.callEvent(\"pitchwheel\", {\n channel: this.channelNumber,\n MSB: MSB,\n LSB: LSB\n });\n this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel] = bend;\n this.voices.forEach(v =>\n // compute pitch modulators\n computeModulators(\n v,\n this.midiControllers,\n 0,\n modulatorSources.pitchWheel\n ));\n this.sendChannelProperty();\n}", "/**\n * Sets the octave tuning for a given channel\n * @this {MidiAudioChannel}\n * @param tuning {Int8Array} LENGTH of 12!\n * relative cent tuning.\n * min -128 max 127.\n */\nexport function setOctaveTuning(tuning)\n{\n if (tuning.length !== 12)\n {\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 {\n this.channelOctaveTuning[i] = tuning[i % 12];\n }\n}", "/**\n * executes a program change\n * @param programNumber {number}\n * @this {MidiAudioChannel}\n */\nexport function programChange(programNumber)\n{\n if (this.lockPreset)\n {\n return;\n }\n // always 128 for percussion\n let bank = this.getBankSelect();\n let sentBank;\n /**\n * @type {BasicPreset}\n */\n let preset;\n \n const isXG = this.isXGChannel;\n // check if override\n if (this.synth.overrideSoundfont)\n {\n const bankWithOffset = bank === 128 ? 128 : bank - this.synth.soundfontBankOffset;\n const p = this.synth.overrideSoundfont.getPresetNoFallback(\n bankWithOffset,\n programNumber,\n isXG\n );\n if (p)\n {\n sentBank = p.bank === 128 ? 128 : p.bank + this.synth.soundfontBankOffset;\n preset = p;\n this.presetUsesOverride = true;\n }\n else\n {\n preset = this.synth.soundfontManager.getPreset(bank, programNumber, isXG);\n const offset = this.synth.soundfontManager.soundfontList\n .find(s => s.soundfont === preset.parentSoundBank).bankOffset;\n sentBank = preset.bank - offset;\n this.presetUsesOverride = false;\n }\n }\n else\n {\n preset = this.synth.soundfontManager.getPreset(bank, programNumber, isXG);\n const offset = this.synth.soundfontManager.soundfontList\n .find(s => s.soundfont === preset.parentSoundBank).bankOffset;\n sentBank = preset.bank - offset;\n this.presetUsesOverride = false;\n }\n this.setPreset(preset);\n this.sentBank = sentBank;\n this.synth.callEvent(\"programchange\", {\n channel: this.channelNumber,\n program: preset.program,\n bank: sentBank\n });\n this.sendChannelProperty();\n}", "import {\n CONTROLLER_TABLE_SIZE,\n CUSTOM_CONTROLLER_TABLE_SIZE,\n customControllers,\n dataEntryStates,\n NON_CC_INDEX_OFFSET\n} from \"./controller_tables.js\";\nimport {\n resetControllers,\n resetControllersRP15Compliant,\n resetParameters\n} from \"../engine_methods/controller_control/reset_controllers.js\";\nimport { renderVoice } from \"../engine_methods/render_voice.js\";\nimport { panVoice } from \"./stereo_panner.js\";\nimport { killNote } from \"../engine_methods/stopping_notes/kill_note.js\";\nimport { setTuning } from \"../engine_methods/tuning_control/set_tuning.js\";\nimport { setModulationDepth } from \"../engine_methods/tuning_control/set_modulation_depth.js\";\nimport { dataEntryFine } from \"../engine_methods/data_entry/data_entry_fine.js\";\nimport { controllerChange } from \"../engine_methods/controller_control/controller_change.js\";\nimport { stopAllNotes } from \"../engine_methods/stopping_notes/stop_all_notes.js\";\nimport { muteChannel } from \"../engine_methods/mute_channel.js\";\nimport { transposeChannel } from \"../engine_methods/tuning_control/transpose_channel.js\";\nimport { dataEntryCoarse } from \"../engine_methods/data_entry/data_entry_coarse.js\";\nimport { noteOn } from \"../engine_methods/note_on.js\";\nimport { noteOff } from \"../engine_methods/stopping_notes/note_off.js\";\nimport { polyPressure } from \"../engine_methods/tuning_control/poly_pressure.js\";\nimport { channelPressure } from \"../engine_methods/tuning_control/channel_pressure.js\";\nimport { pitchWheel } from \"../engine_methods/tuning_control/pitch_wheel.js\";\nimport { setOctaveTuning } from \"../engine_methods/tuning_control/set_octave_tuning.js\";\nimport { programChange } from \"../engine_methods/program_change.js\";\nimport { chooseBank, isSystemXG, parseBankSelect } from \"../../../utils/xg_hacks.js\";\nimport { DEFAULT_PERCUSSION } from \"../../synth_constants.js\";\nimport { modulatorSources } from \"../../../soundfont/basic_soundfont/modulator.js\";\n\n/**\n * This class represents a single MIDI Channel within the synthesizer.\n */\nclass MidiAudioChannel\n{\n /**\n * An array of MIDI controller values and values used by modulators as the source (e.g., pitch bend, bend range, etc.).\n * These are stored as 14-bit values.\n * Refer to controller_tables.js for the index definitions.\n * @type {Int16Array}\n */\n midiControllers = new Int16Array(CONTROLLER_TABLE_SIZE);\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 * @type {boolean[]}\n */\n lockedControllers = Array(CONTROLLER_TABLE_SIZE).fill(false);\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.js for the index definitions.\n * @type {Float32Array}\n */\n customControllers = new Float32Array(CUSTOM_CONTROLLER_TABLE_SIZE);\n \n /**\n * The key shift of the channel (in semitones).\n * @type {number}\n */\n 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: Repeaded every 12 notes\n * @type {Int8Array}\n */\n channelOctaveTuning = new Int8Array(128);\n \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 * @type {number}\n */\n channelTuningCents = 0;\n \n /**\n * Indicates whether the sustain (hold) pedal is active.\n * @type {boolean}\n */\n holdPedal = false;\n \n /**\n * Indicates whether this channel is a drum channel.\n * @type {boolean}\n */\n drumChannel = false;\n \n /**\n * If greater than 0, overrides the velocity value for the channel, otherwise it's disabled.\n * @type {number}\n */\n velocityOverride = 0;\n \n /**\n * Enables random panning for every note played on this channel.\n * @type {boolean}\n */\n randomPan = false;\n \n /**\n * The current state of the data entry for the channel.\n * @type {dataEntryStates}\n */\n dataEntryState = dataEntryStates.Idle;\n \n /**\n * The bank number of the channel (used for patch changes).\n * @type {number}\n */\n bank = 0;\n \n /**\n * The bank number sent as channel properties.\n * @type {number}\n */\n sentBank = 0;\n \n /**\n * The bank LSB number of the channel (used for patch changes in XG mode).\n * @type {number}\n */\n bankLSB = 0;\n \n /**\n * The preset currently assigned to the channel.\n * @type {BasicPreset}\n */\n preset = undefined;\n \n /**\n * Indicates whether the program on this channel is locked.\n * @type {boolean}\n */\n lockPreset = false;\n \n /**\n * Indicates the MIDI system when the preset was locked.\n * @type {SynthSystem}\n */\n lockedSystem = \"gs\";\n \n /**\n * Indicates whether the channel uses a preset from the override soundfont.\n * @type {boolean}\n */\n presetUsesOverride = false;\n \n /**\n * Indicates whether the GS NRPN parameters are enabled for this channel.\n * @type {boolean}\n */\n lockGSNRPNParams = false;\n \n /**\n * The vibrato settings for the channel.\n * @type {Object}\n * @property {number} depth - Depth of the vibrato effect in cents.\n * @property {number} delay - Delay before the vibrato effect starts (in seconds).\n * @property {number} rate - Rate of the vibrato oscillation (in Hz).\n */\n channelVibrato = { delay: 0, depth: 0, rate: 0 };\n \n /**\n * Indicates whether the channel is muted.\n * @type {boolean}\n */\n isMuted = false;\n \n /**\n * An array of voices currently active on the channel.\n * @type {Voice[]}\n */\n voices = [];\n \n /**\n * An array of voices that are sustained on the channel.\n * @type {Voice[]}\n */\n sustainedVoices = [];\n \n /**\n * The channel's number (0-based index)\n * @type {number}\n */\n channelNumber;\n \n /**\n * Parent processor instance.\n * @type {SpessaSynthProcessor}\n */\n synth;\n \n /**\n * Constructs a new MIDI channel\n * @param synth {SpessaSynthProcessor}\n * @param preset {BasicPreset}\n * @param channelNumber {number}\n */\n constructor(synth, preset, channelNumber)\n {\n this.synth = synth;\n this.preset = preset;\n this.channelNumber = channelNumber;\n }\n \n get isXGChannel()\n {\n return isSystemXG(this.synth.system) || (this.lockPreset && isSystemXG(this.lockedSystem));\n }\n \n /**\n * @param type {customControllers|number}\n * @param value {number}\n */\n setCustomController(type, value)\n {\n this.customControllers[type] = value;\n this.updateChannelTuning();\n }\n \n updateChannelTuning()\n {\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] * 100); // RPN channel coarse tuning\n }\n \n /**\n * @param outputLeft {Float32Array} the left output buffer\n * @param outputRight {Float32Array} the right output buffer\n * @param reverbOutputLeft {Float32Array} left output for reverb\n * @param reverbOutputRight {Float32Array} right output for reverb\n * @param chorusOutputLeft {Float32Array} left output for chorus\n * @param chorusOutputRight {Float32Array} right output for chorus\n */\n renderAudio(\n outputLeft, outputRight,\n reverbOutputLeft, reverbOutputRight,\n chorusOutputLeft, chorusOutputRight\n )\n {\n this.voices = this.voices.filter(v => !this.renderVoice(\n v, this.synth.currentSynthTime,\n outputLeft, outputRight,\n reverbOutputLeft, reverbOutputRight,\n chorusOutputLeft, chorusOutputRight\n ));\n }\n \n /**\n * @param locked {boolean}\n */\n setPresetLock(locked)\n {\n this.lockPreset = locked;\n if (locked)\n {\n this.lockedSystem = this.synth.system;\n }\n }\n \n /**\n * @param bank {number}\n * @param isLSB {boolean}\n */\n setBankSelect(bank, isLSB = false)\n {\n if (this.lockPreset)\n {\n return;\n }\n if (isLSB)\n {\n this.bankLSB = bank;\n }\n else\n {\n this.bank = bank;\n const bankLogic = parseBankSelect(\n this.getBankSelect(),\n bank,\n this.synth.system,\n false,\n this.drumChannel,\n this.channelNumber\n );\n switch (bankLogic.drumsStatus)\n {\n default:\n case 0:\n break;\n \n case 1:\n if (this.channelNumber % 16 === DEFAULT_PERCUSSION)\n {\n // cannot disable drums on channel 9\n this.bank = 127;\n }\n break;\n \n case 2:\n this.setDrums(true);\n break;\n }\n }\n }\n \n /**\n * @returns {number}\n */\n getBankSelect()\n {\n return chooseBank(this.bank, this.bankLSB, this.drumChannel, this.isXGChannel);\n }\n \n /**\n * Changes a preset of this channel\n * @param preset {BasicPreset}\n */\n setPreset(preset)\n {\n if (this.lockPreset)\n {\n return;\n }\n delete this.preset;\n this.preset = preset;\n }\n \n /**\n * Sets drums on channel.\n * @param isDrum {boolean}\n */\n setDrums(isDrum)\n {\n if (this.lockPreset)\n {\n return;\n }\n if (this.drumChannel === isDrum)\n {\n return;\n }\n if (isDrum)\n {\n // clear transpose\n this.channelTransposeKeyShift = 0;\n this.drumChannel = true;\n }\n else\n {\n this.drumChannel = false;\n }\n this.presetUsesOverride = false;\n this.synth.callEvent(\"drumchange\", {\n channel: this.channelNumber,\n isDrumChannel: this.drumChannel\n });\n this.programChange(this.preset.program);\n this.sendChannelProperty();\n }\n \n /**\n * Sets a custom vibrato\n * @param depth {number} cents\n * @param rate {number} Hz\n * @param delay {number} seconds\n */\n setVibrato(depth, rate, delay)\n {\n if (this.lockGSNRPNParams)\n {\n return;\n }\n this.channelVibrato.rate = rate;\n this.channelVibrato.delay = delay;\n this.channelVibrato.depth = depth;\n }\n \n disableAndLockGSNRPN()\n {\n this.lockGSNRPNParams = true;\n this.channelVibrato.rate = 0;\n this.channelVibrato.delay = 0;\n this.channelVibrato.depth = 0;\n }\n \n \n /**\n * @typedef {Object} ChannelProperty\n * @property {number} voicesAmount - the channel's current voice amount\n * @property {number} pitchBend - the channel's current pitch bend from -8192 do 8192\n * @property {number} pitchBendRangeSemitones - the pitch bend's range, in semitones\n * @property {boolean} isMuted - indicates whether the channel is muted\n * @property {boolean} isDrum - indicates whether the channel is a drum channel\n * @property {number} transposition - the channel's transposition, in semitones\n * @property {number} bank - the bank number of the current preset\n * @property {number} program - the MIDI program number of the current preset\n */\n \n \n /**\n * Sends this channel's property\n */\n sendChannelProperty()\n {\n if (!this.synth.enableEventSystem)\n {\n return;\n }\n /**\n * @type {ChannelProperty}\n */\n const data = {\n voicesAmount: this.voices.length,\n pitchBend: this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel],\n pitchBendRangeSemitones: this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] / 128,\n isMuted: this.isMuted,\n isDrum: this.drumChannel,\n transposition: this.channelTransposeKeyShift + this.customControllers[customControllers.channelTransposeFine] / 100,\n bank: this.sentBank,\n program: this.preset.program\n };\n this.synth?.callbacks?.channelPropertyChange?.(data, this.channelNumber);\n }\n}\n\n// voice\nMidiAudioChannel.prototype.renderVoice = renderVoice;\nMidiAudioChannel.prototype.panVoice = panVoice;\nMidiAudioChannel.prototype.killNote = killNote;\nMidiAudioChannel.prototype.stopAllNotes = stopAllNotes;\nMidiAudioChannel.prototype.muteChannel = muteChannel;\n\n// MIDI messages\nMidiAudioChannel.prototype.noteOn = noteOn;\nMidiAudioChannel.prototype.noteOff = noteOff;\nMidiAudioChannel.prototype.polyPressure = polyPressure;\nMidiAudioChannel.prototype.channelPressure = channelPressure;\nMidiAudioChannel.prototype.pitchWheel = pitchWheel;\nMidiAudioChannel.prototype.programChange = programChange;\n\n// Tuning\nMidiAudioChannel.prototype.setTuning = setTuning;\nMidiAudioChannel.prototype.setOctaveTuning = setOctaveTuning;\nMidiAudioChannel.prototype.setModulationDepth = setModulationDepth;\nMidiAudioChannel.prototype.transposeChannel = transposeChannel;\n\n// CC\nMidiAudioChannel.prototype.controllerChange = controllerChange;\nMidiAudioChannel.prototype.resetControllers = resetControllers;\nMidiAudioChannel.prototype.resetControllersRP15Compliant = resetControllersRP15Compliant;\nMidiAudioChannel.prototype.resetParameters = resetParameters;\nMidiAudioChannel.prototype.dataEntryFine = dataEntryFine;\nMidiAudioChannel.prototype.dataEntryCoarse = dataEntryCoarse;\n\nexport { MidiAudioChannel };\n", "import { MidiAudioChannel } from \"../engine_components/midi_audio_channel.js\";\n\nimport { DEFAULT_PERCUSSION } from \"../../synth_constants.js\";\n\n/**\n * @param sendEvent {boolean}\n * @this {SpessaSynthProcessor}\n */\nexport function createMidiChannel(sendEvent = false)\n{\n /**\n * @type {MidiAudioChannel}\n */\n const channel = new MidiAudioChannel(this, this.defaultPreset, this.midiAudioChannels.length);\n this.midiAudioChannels.push(channel);\n channel.resetControllers();\n channel.sendChannelProperty();\n if (sendEvent)\n {\n this.callEvent(\"newchannel\", undefined);\n }\n \n if (channel.channelNumber % 16 === DEFAULT_PERCUSSION)\n {\n this.midiAudioChannels[this.midiAudioChannels.length - 1].setDrums(true);\n }\n}", "import { SpessaSynthInfo } from \"../../utils/loggin.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { voiceKilling } from \"./engine_methods/stopping_notes/voice_killing.js\";\nimport {\n ALL_CHANNELS_OR_DIFFERENT_ACTION,\n DEFAULT_PERCUSSION,\n DEFAULT_SYNTH_MODE,\n VOICE_CAP\n} from \"../synth_constants.js\";\nimport { stbvorbis } from \"../../externals/stbvorbis_sync/stbvorbis_sync.min.js\";\nimport { VOLUME_ENVELOPE_SMOOTHING_FACTOR } from \"./engine_components/volume_envelope.js\";\nimport { systemExclusive } from \"./engine_methods/system_exclusive.js\";\nimport { masterParameterType, setMasterParameter } from \"./engine_methods/controller_control/master_parameters.js\";\nimport { resetAllControllers } from \"./engine_methods/controller_control/reset_controllers.js\";\nimport { SoundFontManager } from \"./engine_components/soundfont_manager.js\";\nimport { KeyModifierManager } from \"./engine_components/key_modifier_manager.js\";\nimport { getVoices } from \"./engine_components/voice.js\";\nimport { PAN_SMOOTHING_FACTOR } from \"./engine_components/stereo_panner.js\";\nimport { stopAllChannels } from \"./engine_methods/stopping_notes/stop_all_channels.js\";\nimport { setEmbeddedSoundFont } from \"./engine_methods/soundfont_management/set_embedded_sound_font.js\";\nimport { reloadSoundFont } from \"./engine_methods/soundfont_management/reload_sound_font.js\";\nimport { clearSoundFont } from \"./engine_methods/soundfont_management/clear_sound_font.js\";\nimport { sendPresetList } from \"./engine_methods/soundfont_management/send_preset_list.js\";\nimport { getPreset } from \"./engine_methods/soundfont_management/get_preset.js\";\nimport { transposeAllChannels } from \"./engine_methods/tuning_control/transpose_all_channels.js\";\nimport { setMasterTuning } from \"./engine_methods/tuning_control/set_master_tuning.js\";\nimport { applySynthesizerSnapshot } from \"./snapshot/apply_synthesizer_snapshot.js\";\nimport { createMidiChannel } from \"./engine_methods/create_midi_channel.js\";\nimport { FILTER_SMOOTHING_FACTOR } from \"./engine_components/lowpass_filter.js\";\nimport { getEvent, messageTypes } from \"../../midi/midi_message.js\";\nimport { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { interpolationTypes } from \"./engine_components/enums.js\";\n\n\n/**\n * @typedef {\"gm\"|\"gm2\"|\"gs\"|\"xg\"} SynthSystem\n */\n\n/**\n * main_processor.js\n * purpose: the core synthesis engine\n */\n\n\n/**\n * @typedef {Object} NoteOnCallback\n * @property {number} midiNote - The MIDI note number.\n * @property {number} channel - The MIDI channel number.\n * @property {number} velocity - The velocity of the note.\n */\n\n/**\n * @typedef {Object} NoteOffCallback\n * @property {number} midiNote - The MIDI note number.\n * @property {number} channel - The MIDI channel number.\n */\n\n/**\n * @typedef {Object} DrumChangeCallback\n * @property {number} channel - The MIDI channel number.\n * @property {boolean} isDrumChannel - Indicates if the channel is a drum channel.\n */\n\n/**\n * @typedef {Object} ProgramChangeCallback\n * @property {number} channel - The MIDI channel number.\n * @property {number} program - The program number.\n * @property {number} bank - The bank number.\n */\n\n/**\n * @typedef {Object} ControllerChangeCallback\n * @property {number} channel - The MIDI channel number.\n * @property {number} controllerNumber - The controller number.\n * @property {number} controllerValue - The value of the controller.\n */\n\n/**\n * @typedef {Object} MuteChannelCallback\n * @property {number} channel - The MIDI channel number.\n * @property {boolean} isMuted - Indicates if the channel is muted.\n */\n\n/**\n * @typedef {Object} PresetListChangeCallbackSingle\n * @property {string} presetName - The name of the preset.\n * @property {number} bank - The bank number.\n * @property {number} program - The program number.\n */\n\n/**\n * @typedef {PresetListChangeCallbackSingle[]} PresetListChangeCallback - A list of preset objects.\n */\n\n/**\n * @typedef {Object} SynthDisplayCallback\n * @property {Uint8Array} displayData - The data to display.\n * @property {synthDisplayTypes} displayType - The type of display.\n */\n\n/**\n * @typedef {Object} PitchWheelCallback\n * @property {number} channel - The MIDI channel number.\n * @property {number} MSB - The most significant byte of the pitch-wheel value.\n * @property {number} LSB - The least significant byte of the pitch-wheel value.\n */\n\n/**\n * @typedef {Object} ChannelPressureCallback\n * @property {number} channel - The MIDI channel number.\n * @property {number} pressure - The pressure value.\n */\n\n/**\n * @typedef {Error} SoundfontErrorCallback - The error message for soundfont errors.\n */\n\n/**\n * @typedef {\n * NoteOnCallback |\n * NoteOffCallback |\n * DrumChangeCallback |\n * ProgramChangeCallback |\n * ControllerChangeCallback |\n * MuteChannelCallback |\n * PresetListChangeCallback |\n * PitchWheelCallback |\n * SoundfontErrorCallback |\n * ChannelPressureCallback |\n * SynthDisplayCallback |\n * undefined\n * } EventCallbackData\n */\n\n/**\n * @typedef {\n * \"noteon\"|\n * \"noteoff\"|\n * \"pitchwheel\"|\n * \"controllerchange\"|\n * \"programchange\"|\n * \"channelpressure\"|\n * \"polypressure\" |\n * \"drumchange\"|\n * \"stopall\"|\n * \"newchannel\"|\n * \"mutechannel\"|\n * \"presetlistchange\"|\n * \"allcontrollerreset\"|\n * \"soundfonterror\"|\n * \"synthdisplay\"} EventTypes\n */\n\n\n/**\n * @typedef {Object} SynthMethodOptions\n * @property {number} time - the audio context time when the event should execute, in seconds.\n */\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;\n\nexport const SYNTHESIZER_GAIN = 1.0;\n\n\n// the core synthesis engine of spessasynth.\nclass SpessaSynthProcessor\n{\n \n /**\n * Cached voices for all presets for this synthesizer.\n * Nesting goes like this:\n * this.cachedVoices[bankNumber][programNumber][midiNote][velocity] = a list of Voices for that.\n * @type {Voice[][][][][]}\n */\n cachedVoices = [];\n \n /**\n * Synth's device id: -1 means all\n * @type {number}\n */\n deviceID = ALL_CHANNELS_OR_DIFFERENT_ACTION;\n \n /**\n * Synth's event queue from the main thread\n * @type {{callback: function(), time: number}[]}\n */\n eventQueue = [];\n \n /**\n * Interpolation type used\n * @type {interpolationTypes}\n */\n interpolationType = interpolationTypes.fourthOrder;\n \n /**\n * Global transposition in semitones\n * @type {number}\n */\n transposition = 0;\n \n /**\n * this.tunings[program][key] = tuning\n * @type {MTSProgramTuning[]}\n */\n tunings = [];\n \n \n /**\n * Bank offset for things like embedded RMIDIS. Added for every program change\n * @type {number}\n */\n soundfontBankOffset = 0;\n \n \n /**\n * The volume gain, set by user\n * @type {number}\n */\n masterGain = SYNTHESIZER_GAIN;\n \n /**\n * The volume gain, set by MIDI sysEx\n * @type {number}\n */\n midiVolume = 1;\n \n /**\n * Reverb linear gain\n * @type {number}\n */\n reverbGain = 1;\n /**\n * Chorus linear gain\n * @type {number}\n */\n chorusGain = 1;\n \n /**\n * Maximum number of voices allowed at once\n * @type {number}\n */\n voiceCap = VOICE_CAP;\n \n /**\n * (-1 to 1)\n * @type {number}\n */\n pan = 0.0;\n /**\n * the pan of the left channel\n * @type {number}\n */\n panLeft = 0.5;\n \n /**\n * the pan of the right channel\n * @type {number}\n */\n panRight = 0.5;\n \n /**\n * forces note killing instead of releasing\n * @type {boolean}\n */\n highPerformanceMode = false;\n \n /**\n * Handlese custom key overrides: velocity and preset\n * @type {KeyModifierManager}\n */\n keyModifierManager = new KeyModifierManager();\n \n /**\n * Overrides the main soundfont (embedded, for example)\n * @type {BasicSoundBank}\n */\n overrideSoundfont = undefined;\n \n /**\n * contains all the channels with their voices on the processor size\n * @type {MidiAudioChannel[]}\n */\n midiAudioChannels = [];\n \n /**\n * Controls the bank selection & SysEx\n * @type {SynthSystem}\n */\n system = DEFAULT_SYNTH_MODE;\n /**\n * Current total voices amount\n * @type {number}\n */\n totalVoicesAmount = 0;\n \n /**\n * Synth's default (reset) preset\n * @type {BasicPreset}\n */\n defaultPreset;\n \n defaultPresetUsesOverride = false;\n \n /**\n * Synth's default (reset) drum preset\n * @type {BasicPreset}\n */\n drumPreset;\n \n defaultDrumsUsesOverride = false;\n \n /**\n * Controls if the processor is fully initialized\n * @type {Promise<boolean>}\n */\n processorInitialized = stbvorbis.isInitialized;\n \n /**\n * Current audio time\n * @type {number}\n */\n currentSynthTime = 0;\n \n /**\n * in hertz\n * @type {number}\n */\n sampleRate;\n \n /**\n * @typedef {Object} CallbacksTypedef\n * @property {function?} ready\n * @property {function(EventTypes, EventCallbackData)?} eventCall\n * @property {function(ChannelProperty, number)?} channelPropertyChange\n * @property {function(masterParameterType, number|string)?} masterParameterChange\n */\n \n /**\n * Creates a new synthesizer engine.\n * @param midiChannels {number}\n * @param soundfont {ArrayBuffer}\n * @param enableEventSystem {boolean}\n * @param callbacks {CallbacksTypedef}\n * @param sampleRate {number}\n * @param initialTime {number}\n * @param effectsEnabled {boolean}\n * @param snapshot {SynthesizerSnapshot}\n */\n constructor(\n soundfont,\n sampleRate,\n callbacks,\n effectsEnabled = true,\n enableEventSystem = true,\n initialTime = 0,\n midiChannels = 16,\n snapshot = undefined)\n {\n /**\n * Midi output count\n * @type {number}\n */\n this.midiOutputsCount = midiChannels;\n /**\n * are the chorus and reverb effects enabled?\n * @type {boolean}\n */\n this.effectsEnabled = effectsEnabled;\n let initialChannelCount = this.midiOutputsCount;\n \n /**\n * @type {CallbacksTypedef}\n */\n this.callbacks = callbacks;\n \n this.currentSynthTime = initialTime;\n this.sampleRate = sampleRate;\n \n /**\n * Sample time in seconds\n * @type {number}\n */\n this.sampleTime = 1 / sampleRate;\n \n this.enableEventSystem = enableEventSystem;\n \n \n for (let i = 0; i < 128; i++)\n {\n this.tunings.push([]);\n }\n \n /**\n * @type {SoundFontManager}\n */\n this.soundfontManager = new SoundFontManager(\n soundfont\n );\n this.sendPresetList();\n this.getDefaultPresets();\n \n \n for (let i = 0; i < initialChannelCount; i++)\n {\n this.createMidiChannel(false);\n }\n \n this.midiAudioChannels[DEFAULT_PERCUSSION].preset = this.drumPreset;\n this.midiAudioChannels[DEFAULT_PERCUSSION].drumChannel = true;\n \n // these smoothing factors were tested on 44,100 Hz, adjust them to target sample rate here\n this.volumeEnvelopeSmoothingFactor = VOLUME_ENVELOPE_SMOOTHING_FACTOR * (44100 / sampleRate);\n this.panSmoothingFactor = PAN_SMOOTHING_FACTOR * (44100 / sampleRate);\n this.filterSmoothingFactor = FILTER_SMOOTHING_FACTOR * (44100 / sampleRate);\n \n this._snapshot = snapshot;\n if (this?._snapshot)\n {\n this.applySynthesizerSnapshot(snapshot);\n }\n this.postReady();\n }\n \n /**\n * @returns {number}\n */\n get currentGain()\n {\n return this.masterGain * this.midiVolume;\n }\n \n getDefaultPresets()\n {\n // override this to XG, to set the default preset to NOT be XG drums!\n const sys = this.system;\n this.system = \"xg\";\n this.defaultPreset = this.getPreset(0, 0);\n this.defaultPresetUsesOverride = this.overrideSoundfont?.presets?.indexOf(this.defaultPreset) >= 0;\n this.system = sys;\n this.drumPreset = this.getPreset(128, 0);\n this.defaultDrumsUsesOverride = this.overrideSoundfont?.presets?.indexOf(this.drumPreset) >= 0;\n }\n \n /**\n * @param value {SynthSystem}\n */\n setSystem(value)\n {\n this.system = value;\n this?.callbacks?.masterParameterChange?.(masterParameterType.midiSystem, this.system);\n }\n \n /**\n * @param bank {number}\n * @param program {number}\n * @param midiNote {number}\n * @param velocity {number}\n * @returns {Voice[]|undefined}\n */\n getCachedVoice(bank, program, midiNote, velocity)\n {\n return this.cachedVoices?.[bank]?.[program]?.[midiNote]?.[velocity];\n }\n \n /**\n * @param bank {number}\n * @param program {number}\n * @param midiNote {number}\n * @param velocity {number}\n * @param voices {Voice[]}\n */\n setCachedVoice(bank, program, midiNote, velocity, voices)\n {\n // make sure that it exists\n if (!this.cachedVoices)\n {\n this.cachedVoices = [];\n }\n if (!this.cachedVoices[bank])\n {\n this.cachedVoices[bank] = [];\n }\n if (!this.cachedVoices[bank][program])\n {\n this.cachedVoices[bank][program] = [];\n }\n if (!this.cachedVoices[bank][program][midiNote])\n {\n this.cachedVoices[bank][program][midiNote] = [];\n }\n \n // cache\n this.cachedVoices[bank][program][midiNote][velocity] = voices;\n }\n \n postReady()\n {\n // ensure stbvorbis is fully initialized\n this.processorInitialized.then(() =>\n {\n SpessaSynthInfo(\"%cSpessaSynth is ready!\", consoleColors.recognized);\n this?.callbacks?.ready?.();\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 {Float32Array[]} output stereo channels (L, R)\n * @param reverb {Float32Array[]} reverb stereo channels (L, R)\n * @param chorus {Float32Array[]} chorus stereo channels (L, R)\n */\n renderAudio(outputs, reverb, chorus)\n {\n this.renderAudioSplit(reverb, chorus, Array(16).fill(outputs));\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 {Float32Array[]} reverb stereo channels (L, R)\n * @param chorusChannels {Float32Array[]} chorus stereo channels (L, R)\n * @param separateChannels {Float32Array[][]} a total of 16 stereo pairs (L, R) for each MIDI channel\n */\n renderAudioSplit(reverbChannels, chorusChannels, separateChannels)\n {\n // process event queue\n const time = this.currentSynthTime;\n while (this.eventQueue[0]?.time <= time)\n {\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 // for every channel\n this.totalVoicesAmount = 0;\n this.midiAudioChannels.forEach((channel, index) =>\n {\n if (channel.voices.length < 1 || channel.isMuted)\n {\n // there's nothing to do!\n return;\n }\n let voiceCount = channel.voices.length;\n const ch = index % 16;\n \n // render to the appropriate output\n channel.renderAudio(\n separateChannels[ch][0], separateChannels[ch][1],\n revL, revR,\n chrL, chrR\n );\n \n this.totalVoicesAmount += channel.voices.length;\n // if voice count changed, update voice amount\n if (channel.voices.length !== voiceCount)\n {\n channel.sendChannelProperty();\n }\n });\n \n // advance the time appropriately\n this.currentSynthTime += separateChannels[0][0].length * this.sampleTime;\n }\n \n // noinspection JSUnusedGlobalSymbols\n destroySynthProcessor()\n {\n this.midiAudioChannels.forEach(c =>\n {\n delete c.midiControllers;\n delete c.voices;\n delete c.sustainedVoices;\n delete c.lockedControllers;\n delete c.preset;\n delete c.customControllers;\n });\n delete this.cachedVoices;\n delete this.midiAudioChannels;\n this.soundfontManager.destroyManager();\n delete this.soundfontManager;\n }\n \n /**\n * @param channel {number}\n * @param controllerNumber {number}\n * @param controllerValue {number}\n * @param force {boolean}\n */\n controllerChange(channel, controllerNumber, controllerValue, force = false)\n {\n this.midiAudioChannels[channel].controllerChange(controllerNumber, controllerValue, force);\n }\n \n /**\n * @param channel {number}\n * @param midiNote {number}\n * @param velocity {number}\n */\n noteOn(channel, midiNote, velocity)\n {\n this.midiAudioChannels[channel].noteOn(midiNote, velocity);\n }\n \n /**\n * @param channel {number}\n * @param midiNote {number}\n */\n noteOff(channel, midiNote)\n {\n this.midiAudioChannels[channel].noteOff(midiNote);\n }\n \n /**\n * @param channel {number}\n * @param midiNote {number}\n * @param pressure {number}\n */\n polyPressure(channel, midiNote, pressure)\n {\n this.midiAudioChannels[channel].polyPressure(midiNote, pressure);\n }\n \n /**\n * @param channel {number}\n * @param pressure {number}\n */\n channelPressure(channel, pressure)\n {\n this.midiAudioChannels[channel].channelPressure(pressure);\n }\n \n /**\n * @param channel {number}\n * @param MSB {number}\n * @param LSB {number}\n */\n pitchWheel(channel, MSB, LSB)\n {\n this.midiAudioChannels[channel].pitchWheel(MSB, LSB);\n }\n \n /**\n * @param channel {number}\n * @param programNumber {number}\n */\n programChange(channel, programNumber)\n {\n this.midiAudioChannels[channel].programChange(programNumber);\n }\n \n // noinspection JSUnusedGlobalSymbols\n /**\n * @param message {Uint8Array}\n * @param channelOffset {number}\n * @param force {boolean} cool stuff\n * @param options {SynthMethodOptions}\n */\n processMessage(message, channelOffset, force, options)\n {\n const call = () =>\n {\n const statusByteData = getEvent(message[0]);\n \n const channel = statusByteData.channel + channelOffset;\n // process the event\n switch (statusByteData.status)\n {\n case messageTypes.noteOn:\n const velocity = message[2];\n if (velocity > 0)\n {\n this.noteOn(channel, message[1], velocity);\n }\n else\n {\n this.noteOff(channel, message[1]);\n }\n break;\n \n case messageTypes.noteOff:\n if (force)\n {\n this.midiAudioChannels[channel].killNote(message[1]);\n }\n else\n {\n this.noteOff(channel, message[1]);\n }\n break;\n \n case messageTypes.pitchBend:\n this.pitchWheel(channel, message[2], message[1]);\n break;\n \n case messageTypes.controllerChange:\n this.controllerChange(channel, message[1], message[2], force);\n break;\n \n case messageTypes.programChange:\n this.programChange(channel, message[1]);\n break;\n \n case messageTypes.polyPressure:\n this.polyPressure(channel, message[0], message[1]);\n break;\n \n case messageTypes.channelPressure:\n this.channelPressure(channel, message[1]);\n break;\n \n case messageTypes.systemExclusive:\n this.systemExclusive(new IndexedByteArray(message.slice(1)), channelOffset);\n break;\n \n case messageTypes.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 {\n this.eventQueue.push({\n callback: call.bind(this),\n time: time\n });\n this.eventQueue.sort((e1, e2) => e1.time - e2.time);\n }\n else\n {\n call();\n }\n }\n \n /**\n * @param volume {number} 0 to 1\n */\n setMIDIVolume(volume)\n {\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.midiVolume = Math.pow(volume, Math.E);\n this.setMasterParameter(masterParameterType.masterPan, this.pan);\n }\n \n /**\n * Calls synth event\n * @param eventName {EventTypes} the event name\n * @param eventData {EventCallbackData}\n * @this {SpessaSynthProcessor}\n */\n callEvent(eventName, eventData)\n {\n this?.callbacks?.eventCall?.(eventName, eventData);\n }\n}\n\n// include other methods\n// voice related\nSpessaSynthProcessor.prototype.voiceKilling = voiceKilling;\nSpessaSynthProcessor.prototype.getVoices = getVoices;\n\n// system-exclusive related\nSpessaSynthProcessor.prototype.systemExclusive = systemExclusive;\n\n// channel related\nSpessaSynthProcessor.prototype.stopAllChannels = stopAllChannels;\nSpessaSynthProcessor.prototype.createMidiChannel = createMidiChannel;\nSpessaSynthProcessor.prototype.resetAllControllers = resetAllControllers;\n\n// master parameter related\nSpessaSynthProcessor.prototype.setMasterParameter = setMasterParameter;\n\n// tuning related\nSpessaSynthProcessor.prototype.transposeAllChannels = transposeAllChannels;\nSpessaSynthProcessor.prototype.setMasterTuning = setMasterTuning;\n\n// program related\nSpessaSynthProcessor.prototype.getPreset = getPreset;\nSpessaSynthProcessor.prototype.reloadSoundFont = reloadSoundFont;\nSpessaSynthProcessor.prototype.clearSoundFont = clearSoundFont;\nSpessaSynthProcessor.prototype.setEmbeddedSoundFont = setEmbeddedSoundFont;\nSpessaSynthProcessor.prototype.sendPresetList = sendPresetList;\n\n// snapshot related\nSpessaSynthProcessor.prototype.applySynthesizerSnapshot = applySynthesizerSnapshot;\n\nexport { SpessaSynthProcessor };", "/**\n * Reads as Big endian\n * @param dataArray {IndexedByteArray}\n * @param bytesAmount {number}\n * @returns {number}\n */\nexport function readBytesAsUintBigEndian(dataArray, bytesAmount)\n{\n let out = 0;\n for (let i = 8 * (bytesAmount - 1); i >= 0; i -= 8)\n {\n out |= (dataArray[dataArray.currentIndex++] << i);\n }\n return out >>> 0;\n}\n\n/**\n * @param number {number}\n * @param bytesAmount {number}\n * @returns {number[]}\n */\nexport function writeBytesAsUintBigEndian(number, bytesAmount)\n{\n const bytes = new Array(bytesAmount).fill(0);\n for (let i = bytesAmount - 1; i >= 0; i--)\n {\n bytes[i] = number & 0xFF;\n number >>= 8;\n }\n \n return bytes;\n}", "import { getEvent, messageTypes } from \"../midi/midi_message.js\";\nimport { consoleColors } from \"../utils/other.js\";\nimport { SpessaSynthWarn } from \"../utils/loggin.js\";\nimport { readBytesAsUintBigEndian } from \"../utils/byte_functions/big_endian.js\";\n\n/**\n * Processes a single event\n * @param event {MIDIMessage}\n * @param trackIndex {number}\n * @this {SpessaSynthSequencer}\n * @private\n */\nexport function _processEvent(event, trackIndex)\n{\n if (this.sendMIDIMessages)\n {\n if (event.messageStatusByte >= 0x80)\n {\n this.sendMIDIMessage([event.messageStatusByte, ...event.messageData]);\n return;\n }\n }\n const statusByteData = getEvent(event.messageStatusByte);\n const offset = this.midiPortChannelOffsets[this.midiPorts[trackIndex]] || 0;\n statusByteData.channel += offset;\n // process the event\n switch (statusByteData.status)\n {\n case messageTypes.noteOn:\n const velocity = event.messageData[1];\n if (velocity > 0)\n {\n this.synth.noteOn(statusByteData.channel, event.messageData[0], velocity);\n this.playingNotes.push({\n midiNote: event.messageData[0],\n channel: statusByteData.channel,\n velocity: velocity\n });\n }\n else\n {\n this.synth.noteOff(statusByteData.channel, event.messageData[0]);\n const toDelete = this.playingNotes.findIndex(n =>\n n.midiNote === event.messageData[0] && n.channel === statusByteData.channel);\n if (toDelete !== -1)\n {\n this.playingNotes.splice(toDelete, 1);\n }\n }\n break;\n \n case messageTypes.noteOff:\n this.synth.noteOff(statusByteData.channel, event.messageData[0]);\n const toDelete = this.playingNotes.findIndex(n =>\n n.midiNote === event.messageData[0] && n.channel === statusByteData.channel);\n if (toDelete !== -1)\n {\n this.playingNotes.splice(toDelete, 1);\n }\n break;\n \n case messageTypes.pitchBend:\n this.synth.pitchWheel(statusByteData.channel, event.messageData[1], event.messageData[0]);\n break;\n \n case messageTypes.controllerChange:\n // empty tracks cannot cc change\n if (this.midiData.isMultiPort && this.midiData.usedChannelsOnTrack[trackIndex].size === 0)\n {\n return;\n }\n this.synth.controllerChange(statusByteData.channel, event.messageData[0], event.messageData[1]);\n break;\n \n case messageTypes.programChange:\n // empty tracks cannot program change\n if (this.midiData.isMultiPort && this.midiData.usedChannelsOnTrack[trackIndex].size === 0)\n {\n return;\n }\n this.synth.programChange(statusByteData.channel, event.messageData[0]);\n break;\n \n case messageTypes.polyPressure:\n this.synth.polyPressure(statusByteData.channel, event.messageData[0], event.messageData[1]);\n break;\n \n case messageTypes.channelPressure:\n this.synth.channelPressure(statusByteData.channel, event.messageData[0]);\n break;\n \n case messageTypes.systemExclusive:\n this.synth.systemExclusive(event.messageData, offset);\n break;\n \n case messageTypes.setTempo:\n event.messageData.currentIndex = 0;\n let tempoBPM = 60000000 / readBytesAsUintBigEndian(event.messageData, 3);\n this.oneTickToSeconds = 60 / (tempoBPM * this.midiData.timeDivision);\n if (this.oneTickToSeconds === 0)\n {\n this.oneTickToSeconds = 60 / (120 * this.midiData.timeDivision);\n SpessaSynthWarn(\"invalid tempo! falling back to 120 BPM\");\n tempoBPM = 120;\n }\n break;\n \n // recognized but ignored\n case messageTypes.timeSignature:\n case messageTypes.endOfTrack:\n case messageTypes.midiChannelPrefix:\n case messageTypes.songPosition:\n case messageTypes.activeSensing:\n case messageTypes.keySignature:\n case messageTypes.sequenceNumber:\n case messageTypes.sequenceSpecific:\n case messageTypes.text:\n case messageTypes.lyric:\n case messageTypes.copyright:\n case messageTypes.trackName:\n case messageTypes.marker:\n case messageTypes.cuePoint:\n case messageTypes.instrumentName:\n case messageTypes.programName:\n break;\n \n \n case messageTypes.midiPort:\n this.assignMIDIPort(trackIndex, event.messageData[0]);\n break;\n \n case messageTypes.reset:\n this.synth.stopAllChannels();\n this.synth.resetAllControllers();\n break;\n \n default:\n SpessaSynthWarn(\n `%cUnrecognized Event: %c${event.messageStatusByte}%c status byte: %c${Object.keys(\n messageTypes).find(k => messageTypes[k] === statusByteData.status)}`,\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 {\n this?.onMetaEvent?.(event, trackIndex);\n }\n}\n\n/**\n * Adds 16 channels to the synth\n * @this {SpessaSynthSequencer}\n * @private\n */\nexport function _addNewMidiPort()\n{\n for (let i = 0; i < 16; i++)\n {\n this.synth.createMidiChannel(true);\n }\n}", "/**\n * Processes a single tick\n * @this {SpessaSynthSequencer}\n */\nexport function processTick()\n{\n if (!this.isActive)\n {\n return;\n }\n let current = this.currentTime;\n while (this.playedTime < current)\n {\n // find the next event\n let trackIndex = this._findFirstEventIndex();\n let event = this.tracks[trackIndex][this.eventIndex[trackIndex]];\n this._processEvent(event, trackIndex);\n \n this.eventIndex[trackIndex]++;\n \n // find the next event\n trackIndex = this._findFirstEventIndex();\n if (this.tracks[trackIndex].length <= this.eventIndex[trackIndex])\n {\n // the song has ended\n if (this.loop)\n {\n this.setTimeTicks(this.midiData.loop.start);\n return;\n }\n this.eventIndex[trackIndex]--;\n this.pause(true);\n if (this.songs.length > 1)\n {\n this.nextSong();\n }\n return;\n }\n let eventNext = this.tracks[trackIndex][this.eventIndex[trackIndex]];\n this.playedTime += this.oneTickToSeconds * (eventNext.ticks - event.ticks);\n \n const canLoop = this.loop && (this.loopCount > 0 || this.loopCount === -1);\n \n // if we reached loop.end\n if ((this.midiData.loop.end <= event.ticks) && canLoop)\n {\n // loop\n if (this.loopCount !== Infinity)\n {\n this.loopCount--;\n this?.onLoopCountChange?.(this.loopCount);\n }\n this.setTimeTicks(this.midiData.loop.start);\n return;\n }\n // if the song has ended\n else if (current >= this.duration)\n {\n if (canLoop)\n {\n // loop\n if (this.loopCount !== Infinity)\n {\n this.loopCount--;\n this?.onLoopCountChange?.(this.loopCount);\n }\n this.setTimeTicks(this.midiData.loop.start);\n return;\n }\n // stop the playback\n this.eventIndex[trackIndex]--;\n this.pause(true);\n if (this.songs.length > 1)\n {\n this.nextSong();\n }\n return;\n }\n }\n}\n\n\n/**\n * @returns {number} the index of the first to the current played time\n * @this {SpessaSynthSequencer}\n */\nexport function _findFirstEventIndex()\n{\n let index = 0;\n let ticks = Infinity;\n this.tracks.forEach((track, i) =>\n {\n if (this.eventIndex[i] >= track.length)\n {\n return;\n }\n if (track[this.eventIndex[i]].ticks < ticks)\n {\n index = i;\n ticks = track[this.eventIndex[i]].ticks;\n }\n });\n return index;\n}", "/**\n * This is the base type for MIDI files. It contains all the \"metadata\" and information.\n * It extends to:\n * - BasicMIDI, which contains the actual track data of the MIDI file. Essentially the MIDI file itself.\n * - MIDIData, which contains all properties that MIDI does, except for tracks and the embedded soundfont.\n * MIDIData is the \"shell\" of the file which is available on the main thread at all times, containing the metadata.\n */\nclass MIDISequenceData\n{\n /**\n * The time division of the sequence, representing the number of ticks per beat.\n * @type {number}\n */\n timeDivision = 0;\n \n /**\n * The duration of the sequence, in seconds.\n * @type {number}\n */\n 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 * @type {{ticks: number, tempo: number}[]}\n */\n tempoChanges = [{ ticks: 0, tempo: 120 }];\n \n /**\n * A string containing the copyright information for the MIDI sequence if detected.\n * @type {string}\n */\n copyright = \"\";\n \n /**\n * The number of tracks in the MIDI sequence.\n * @type {number}\n */\n tracksAmount = 0;\n \n /**\n * The track names in the MIDI file, an empty string if not set.\n * @type {string[]}\n */\n trackNames = [];\n \n /**\n * An array containing the lyrics of the sequence, stored as binary chunks (Uint8Array).\n * @type {Uint8Array[]}\n */\n lyrics = [];\n \n /**\n * An array of tick positions where lyrics events occur in the sequence.\n * @type {number[]}\n */\n lyricsTicks = [];\n \n /**\n * The tick position of the first note-on event in the MIDI sequence.\n * @type {number}\n */\n firstNoteOn = 0;\n \n /**\n * The MIDI key range used in the sequence, represented by a minimum and maximum note value.\n * @type {{min: number, max: number}}\n */\n keyRange = { 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 * @type {number}\n */\n lastVoiceEventTick = 0;\n \n /**\n * An array of MIDI port numbers used by each track in the sequence.\n * @type {number[]}\n */\n midiPorts = [0];\n \n /**\n * An array of channel offsets for each MIDI port, using the SpessaSynth method.\n * @type {number[]}\n */\n midiPortChannelOffsets = [0];\n \n /**\n * A list of sets, where each set contains the MIDI channels used by each track in the sequence.\n * @type {Set<number>[]}\n */\n usedChannelsOnTrack = [];\n \n /**\n * The loop points (in ticks) of the sequence, including both start and end points.\n * @type {{start: number, end: number}}\n */\n loop = { start: 0, end: 0 };\n \n /**\n * The name of the MIDI sequence.\n * @type {string}\n */\n midiName = \"\";\n \n /**\n * A boolean indicating if the sequence's name is the same as the file name.\n * @type {boolean}\n */\n midiNameUsesFileName = false;\n \n /**\n * The file name of the MIDI sequence, if provided during parsing.\n * @type {string}\n */\n fileName = \"\";\n \n /**\n * The raw, encoded MIDI name, represented as a Uint8Array.\n * Useful when the MIDI file uses a different code page.\n * @type {Uint8Array}\n */\n rawMidiName;\n \n /**\n * The format of the MIDI file, which can be 0, 1, or 2, indicating the type of the MIDI file.\n * @type {number}\n */\n format = 0;\n \n /**\n * The RMID (Resource-Interchangeable MIDI) info data, if the file is RMID formatted.\n * Otherwise, this field is undefined.\n * Chunk type (e.g. \"INAM\"): Chunk data as a binary array.\n * @type {Object<string, IndexedByteArray>}\n */\n RMIDInfo = {};\n \n /**\n * The bank offset used for RMID files.\n * @type {number}\n */\n bankOffset = 0;\n \n /**\n * If the MIDI file is a Soft Karaoke file (.kar), this flag is set to true.\n * https://www.mixagesoftware.com/en/midikit/help/HTML/karaoke_formats.html\n * @type {boolean}\n */\n isKaraokeFile = false;\n \n /**\n * Indicates if this file is a Multi-Port MIDI file.\n * @type {boolean}\n */\n isMultiPort = false;\n \n /**\n * Converts ticks to time in seconds\n * @param ticks {number} time in MIDI ticks\n * @returns {number} time in seconds\n */\n MIDIticksToSeconds(ticks)\n {\n let totalSeconds = 0;\n \n while (ticks > 0)\n {\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 let tempo = this.tempoChanges.find(v => v.ticks < ticks);\n \n // calculate the difference and tempo time\n let timeSinceLastTempo = ticks - tempo.ticks;\n totalSeconds += (timeSinceLastTempo * 60) / (tempo.tempo * this.timeDivision);\n ticks -= timeSinceLastTempo;\n }\n \n return totalSeconds;\n }\n \n /**\n * INTERNAL USE ONLY!\n * @param sequence {MIDISequenceData}\n * @protected\n */\n _copyFromSequence(sequence)\n {\n // properties can be assigned\n this.midiName = sequence.midiName;\n this.midiNameUsesFileName = sequence.midiNameUsesFileName;\n this.fileName = sequence.fileName;\n this.timeDivision = sequence.timeDivision;\n this.duration = sequence.duration;\n this.copyright = sequence.copyright;\n this.tracksAmount = sequence.tracksAmount;\n this.firstNoteOn = sequence.firstNoteOn;\n this.lastVoiceEventTick = sequence.lastVoiceEventTick;\n this.format = sequence.format;\n this.bankOffset = sequence.bankOffset;\n this.isKaraokeFile = sequence.isKaraokeFile;\n this.isMultiPort = sequence.isMultiPort;\n \n // copying arrays\n this.tempoChanges = [...sequence.tempoChanges];\n this.lyrics = sequence.lyrics.map(arr => new Uint8Array(arr));\n this.lyricsTicks = [...sequence.lyricsTicks];\n this.midiPorts = [...sequence.midiPorts];\n this.trackNames = [...sequence.trackNames];\n this.midiPortChannelOffsets = [...sequence.midiPortChannelOffsets];\n this.usedChannelsOnTrack = sequence.usedChannelsOnTrack.map(set => new Set(set));\n this.rawMidiName = sequence.rawMidiName ? new Uint8Array(sequence.rawMidiName) : undefined;\n \n // copying objects\n this.loop = { ...sequence.loop };\n this.keyRange = { ...sequence.keyRange };\n this.RMIDInfo = { ...sequence.RMIDInfo };\n }\n}\n\nexport { MIDISequenceData };", "/**\n * Reads VLQ From a MIDI byte array\n * @param MIDIbyteArray {IndexedByteArray}\n * @returns {number}\n */\nexport function readVariableLengthQuantity(MIDIbyteArray)\n{\n let out = 0;\n while (MIDIbyteArray)\n {\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 {\n break;\n }\n }\n return out;\n}\n\n/**\n * Write a VLQ from a number to a byte array\n * @param number {number}\n * @returns {number[]}\n */\nexport function writeVariableLengthQuantity(number)\n{\n // Add the first byte\n let bytes = [number & 127];\n number >>= 7;\n \n // Continue processing the remaining bytes\n while (number > 0)\n {\n bytes.unshift((number & 127) | 128);\n number >>= 7;\n }\n return bytes;\n}", "import { messageTypes } from \"../midi_message.js\";\nimport { writeVariableLengthQuantity } from \"../../utils/byte_functions/variable_length_quantity.js\";\nimport { writeBytesAsUintBigEndian } from \"../../utils/byte_functions/big_endian.js\";\n\n/**\n * Exports the midi as a standard MIDI file\n * @this {BasicMIDI}\n */\nexport function writeMIDI()\n{\n const midi = this;\n if (!midi.tracks)\n {\n throw new Error(\"MIDI has no tracks!\");\n }\n /**\n * @type {Uint8Array[]}\n */\n const binaryTrackData = [];\n for (const track of midi.tracks)\n {\n const binaryTrack = [];\n let currentTick = 0;\n let runningByte = undefined;\n for (const event of track)\n {\n // Ticks stored in MIDI are absolute, but SMF wants relative. Convert them here.\n const deltaTicks = event.ticks - currentTick;\n /**\n * @type {number[]}\n */\n let messageData;\n // determine the message\n if (event.messageStatusByte <= messageTypes.sequenceSpecific)\n {\n // this is a meta-message\n // syntax is FF<type><length><data>\n messageData = [0xff, event.messageStatusByte, ...writeVariableLengthQuantity(event.messageData.length), ...event.messageData];\n }\n else if (event.messageStatusByte === messageTypes.systemExclusive)\n {\n // this is a system exclusive message\n // syntax is F0<length><data>\n messageData = [0xf0, ...writeVariableLengthQuantity(event.messageData.length), ...event.messageData];\n }\n else\n {\n // this is a midi message\n messageData = [];\n if (runningByte !== event.messageStatusByte)\n {\n // Running byte was not the byte we want. Add the byte here.\n runningByte = event.messageStatusByte;\n // add the status byte to the midi\n messageData.push(event.messageStatusByte);\n }\n // add the data\n messageData.push(...event.messageData);\n }\n // write VLQ\n binaryTrack.push(...writeVariableLengthQuantity(deltaTicks));\n // write the message\n binaryTrack.push(...messageData);\n currentTick += deltaTicks;\n }\n binaryTrackData.push(new Uint8Array(binaryTrack));\n }\n \n /**\n * @param text {string}\n * @param arr {number[]}\n */\n function writeText(text, arr)\n {\n for (let i = 0; i < text.length; i++)\n {\n arr.push(text.charCodeAt(i));\n }\n }\n \n // write the file\n const binaryData = [];\n // write header\n writeText(\"MThd\", binaryData); // MThd\n binaryData.push(...writeBytesAsUintBigEndian(6, 4)); // length\n binaryData.push(0, midi.format); // format\n binaryData.push(...writeBytesAsUintBigEndian(midi.tracksAmount, 2)); // num tracks\n binaryData.push(...writeBytesAsUintBigEndian(midi.timeDivision, 2)); // time division\n \n // write tracks\n for (const track of binaryTrackData)\n {\n // write track header\n writeText(\"MTrk\", binaryData); // MTrk\n binaryData.push(...writeBytesAsUintBigEndian(track.length, 4)); // length\n binaryData.push(...track); // write data\n }\n return new Uint8Array(binaryData);\n}", "/**\n * @param e {MIDIMessage}\n * @returns boolean\n */\nexport function isXGOn(e)\n{\n return e.messageData[0] === 0x43 && // Yamaha\n e.messageData[2] === 0x4C && // XG ON\n e.messageData[5] === 0x7E &&\n e.messageData[6] === 0x00;\n}\n\n/**\n * @param e {MIDIMessage}\n * @returns boolean\n */\nexport function isGSDrumsOn(e)\n{\n return e.messageData[0] === 0x41 && // roland\n e.messageData[2] === 0x42 && // GS\n e.messageData[3] === 0x12 && // GS\n e.messageData[4] === 0x40 && // system parameter\n (e.messageData[5] & 0x10) !== 0 && // part parameter\n e.messageData[6] === 0x15; // drum pars\n}\n\n/**\n * @param e {MIDIMessage}\n * @returns boolean\n */\nexport function isGSOn(e)\n{\n return e.messageData[0] === 0x41 // roland\n && e.messageData[2] === 0x42 // GS\n && e.messageData[6] === 0x7F; // Mode set\n}\n\n/**\n * @param e {MIDIMessage}\n * @returns boolean\n */\nexport function isGMOn(e)\n{\n return e.messageData[0] === 0x7E // non realtime\n && e.messageData[2] === 0x09 // gm system\n && e.messageData[3] === 0x01; // gm1\n}\n\n/**\n * @param e {MIDIMessage}\n * @returns boolean\n */\nexport function isGM2On(e)\n{\n return e.messageData[0] === 0x7E // non realtime\n && e.messageData[2] === 0x09 // gm system\n && e.messageData[3] === 0x03; // gm2\n}", "import { messageTypes, midiControllers, MIDIMessage } from \"../midi_message.js\";\nimport { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../../utils/loggin.js\";\nimport { consoleColors } from \"../../utils/other.js\";\n\nimport { customControllers } from \"../../synthetizer/audio_engine/engine_components/controller_tables.js\";\nimport { DEFAULT_PERCUSSION } from \"../../synthetizer/synth_constants.js\";\nimport { isGM2On, isGMOn, isGSOn, isXGOn } from \"../../utils/sysex_detector.js\";\nimport { isSystemXG, isXGDrums, XG_SFX_VOICE } from \"../../utils/xg_hacks.js\";\n\n/**\n * @param ticks {number}\n * @returns {MIDIMessage}\n */\nexport function getGsOn(ticks)\n{\n return new MIDIMessage(\n ticks,\n messageTypes.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\n/**\n * @param channel {number}\n * @param cc {number}\n * @param value {number}\n * @param ticks {number}\n * @returns {MIDIMessage}\n */\nfunction getControllerChange(channel, cc, value, ticks)\n{\n return new MIDIMessage(\n ticks,\n messageTypes.controllerChange | (channel % 16),\n new IndexedByteArray([cc, value])\n );\n}\n\n/**\n * @param channel {number}\n * @param ticks {number}\n * @returns {MIDIMessage}\n */\nfunction getDrumChange(channel, ticks)\n{\n const chanAddress = 0x10 | [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 messageTypes.systemExclusive,\n new IndexedByteArray([\n ...sysexData,\n checksum,\n 0xF7\n ])\n );\n}\n\n/**\n * @typedef {Object} DesiredProgramChange\n * @property {number} channel - The channel number.\n * @property {number} program - The program number.\n * @property {number} bank - The bank number.\n * @property {boolean} isDrum - Indicates if the channel is a drum channel.\n * If it is, then the bank number is ignored.\n */\n\n/**\n * @typedef {Object} DesiredControllerChange\n * @property {number} channel - The channel number.\n * @property {number} controllerNumber - The MIDI controller number.\n * @property {number} controllerValue - The new controller value.\n */\n\n/**\n * @typedef {Object} DesiredChanneltranspose\n * @property {number} channel - The channel number.\n * @property {number} keyShift - The number of semitones to transpose.\n * Note that this can use floating point numbers,\n * which will be used to fine-tune the pitch in cents using RPN.\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 * @this {BasicMIDI}\n * @param {DesiredProgramChange[]} desiredProgramChanges - The programs to set on given channels.\n * @param {DesiredControllerChange[]} desiredControllerChanges - The controllers to set on given channels.\n * @param {number[]} desiredChannelsToClear - The channels to remove from the sequence.\n * @param {DesiredChanneltranspose[]} desiredChannelsToTranspose - The channels to transpose.\n */\nexport function modifyMIDI(\n desiredProgramChanges = [],\n desiredControllerChanges = [],\n desiredChannelsToClear = [],\n desiredChannelsToTranspose = []\n)\n{\n const midi = this;\n SpessaSynthGroupCollapsed(\"%cApplying changes to the MIDI file...\", consoleColors.info);\n \n SpessaSynthInfo(\"Desired program changes:\", desiredProgramChanges);\n SpessaSynthInfo(\"Desired CC changes:\", desiredControllerChanges);\n SpessaSynthInfo(\"Desired channels to clear:\", desiredChannelsToClear);\n SpessaSynthInfo(\"Desired channels to transpose:\", desiredChannelsToTranspose);\n \n /**\n * @type {Set<number>}\n */\n const channelsToChangeProgram = new Set();\n desiredProgramChanges.forEach(c =>\n {\n channelsToChangeProgram.add(c.channel);\n });\n \n \n // go through all events one by one\n let system = \"gs\";\n let addedGs = false;\n /**\n * indexes for tracks\n * @type {number[]}\n */\n const eventIndexes = Array(midi.tracks.length).fill(0);\n let remainingTracks = midi.tracks.length;\n \n function findFirstEventIndex()\n {\n let index = 0;\n let ticks = Infinity;\n midi.tracks.forEach((track, i) =>\n {\n if (eventIndexes[i] >= track.length)\n {\n return;\n }\n if (track[eventIndexes[i]].ticks < ticks)\n {\n index = i;\n ticks = track[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 * @type {number[]}\n */\n const midiPorts = midi.midiPorts.slice();\n /**\n * midi port: channel offset\n * @type {Object<number, number>}\n */\n const midiPortChannelOffsets = {};\n let midiPortChannelOffset = 0;\n \n function assignMIDIPort(trackNum, port)\n {\n // do not assign ports to empty tracks\n if (midi.usedChannelsOnTrack[trackNum].size === 0)\n {\n return;\n }\n \n // assign new 16 channels if the port is not occupied yet\n if (midiPortChannelOffset === 0)\n {\n midiPortChannelOffset += 16;\n midiPortChannelOffsets[port] = 0;\n }\n \n if (midiPortChannelOffsets[port] === undefined)\n {\n midiPortChannelOffsets[port] = midiPortChannelOffset;\n midiPortChannelOffset += 16;\n }\n \n midiPorts[trackNum] = port;\n }\n \n // assign port offsets\n midi.midiPorts.forEach((port, trackIndex) =>\n {\n assignMIDIPort(trackIndex, port);\n });\n \n const channelsAmount = midiPortChannelOffset;\n /**\n * Tracks if the channel already had its first note on\n * @type {boolean[]}\n */\n const isFirstNoteOn = Array(channelsAmount).fill(true);\n \n /**\n * MIDI key transpose\n * @type {number[]}\n */\n const coarseTranspose = Array(channelsAmount).fill(0);\n /**\n * RPN fine transpose\n * @type {number[]}\n */\n const fineTranspose = Array(channelsAmount).fill(0);\n desiredChannelsToTranspose.forEach(transpose =>\n {\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 {\n let trackNum = findFirstEventIndex();\n const track = midi.tracks[trackNum];\n if (eventIndexes[trackNum] >= track.length)\n {\n remainingTracks--;\n continue;\n }\n const index = eventIndexes[trackNum]++;\n const e = track[index];\n \n const deleteThisEvent = () =>\n {\n track.splice(index, 1);\n eventIndexes[trackNum]--;\n };\n \n /**\n * @param e {MIDIMessage}\n * @param offset{number}\n */\n const addEventBefore = (e, offset = 0) =>\n {\n track.splice(index + offset, 0, e);\n eventIndexes[trackNum]++;\n };\n \n \n let portOffset = midiPortChannelOffsets[midiPorts[trackNum]] || 0;\n if (e.messageStatusByte === messageTypes.midiPort)\n {\n assignMIDIPort(trackNum, e.messageData[0]);\n continue;\n }\n // don't clear meta\n if (e.messageStatusByte <= messageTypes.sequenceSpecific && e.messageStatusByte >= messageTypes.sequenceNumber)\n {\n continue;\n }\n const status = e.messageStatusByte & 0xF0;\n const midiChannel = e.messageStatusByte & 0xF;\n const channel = midiChannel + portOffset;\n // clear channel?\n if (desiredChannelsToClear.indexOf(channel) !== -1)\n {\n deleteThisEvent();\n continue;\n }\n switch (status)\n {\n case messageTypes.noteOn:\n // is it first?\n if (isFirstNoteOn[channel])\n {\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.filter(c => c.channel === channel).forEach(change =>\n {\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 {\n // add rpn\n // 64 is the center, 96 = 50 cents up\n const centsCoarse = (fineTune * 64) + 64;\n const rpnCoarse = getControllerChange(midiChannel, midiControllers.RPNMsb, 0, e.ticks);\n const rpnFine = getControllerChange(midiChannel, midiControllers.RPNLsb, 1, e.ticks);\n const dataEntryCoarse = getControllerChange(\n channel,\n midiControllers.dataEntryMsb,\n centsCoarse,\n e.ticks\n );\n const dataEntryFine = getControllerChange(\n midiChannel,\n midiControllers.lsbForControl6DataEntry,\n 0,\n e.ticks\n );\n addEventBefore(dataEntryFine);\n addEventBefore(dataEntryCoarse);\n addEventBefore(rpnFine);\n addEventBefore(rpnCoarse);\n \n }\n \n if (channelsToChangeProgram.has(channel))\n {\n const change = desiredProgramChanges.find(c => c.channel === channel);\n let desiredBank = Math.max(0, Math.min(change.bank, 127));\n const desiredProgram = change.program;\n SpessaSynthInfo(\n `%cSetting %c${change.channel}%c to %c${desiredBank}:${desiredProgram}%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 \n // add program change\n const programChange = new MIDIMessage(\n e.ticks,\n messageTypes.programChange | midiChannel,\n new IndexedByteArray([\n desiredProgram\n ])\n );\n addEventBefore(programChange);\n \n const addBank = (isLSB, v) =>\n {\n const bankChange = getControllerChange(\n midiChannel,\n isLSB ? midiControllers.lsbForControl0BankSelect : midiControllers.bankSelect,\n v,\n e.ticks\n );\n addEventBefore(bankChange);\n };\n \n // on xg, add lsb\n if (isSystemXG(system))\n {\n // xg drums: msb can be 120, 126 or 127\n if (change.isDrum)\n {\n SpessaSynthInfo(\n `%cAdding XG Drum change on track %c${trackNum}`,\n consoleColors.recognized,\n consoleColors.value\n );\n addBank(false, isXGDrums(desiredBank) ? desiredBank : 127);\n addBank(true, 0);\n }\n else\n {\n // sfx voice is set via MSB\n if (desiredBank === XG_SFX_VOICE)\n {\n addBank(false, XG_SFX_VOICE);\n addBank(true, 0);\n }\n else\n {\n // add variation as LSB\n addBank(false, 0);\n addBank(true, desiredBank);\n }\n }\n }\n else\n {\n // add just msb\n addBank(false, desiredBank);\n \n if (change.isDrum && 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 }\n // transpose key (for zero it won't change anyway)\n e.messageData[0] += coarseTranspose[channel];\n break;\n \n case messageTypes.noteOff:\n e.messageData[0] += coarseTranspose[channel];\n break;\n \n case messageTypes.programChange:\n // do we delete it?\n if (channelsToChangeProgram.has(channel))\n {\n // this channel has program change. BEGONE!\n deleteThisEvent();\n continue;\n }\n break;\n \n case messageTypes.controllerChange:\n const ccNum = e.messageData[0];\n const changes = desiredControllerChanges.find(c => c.channel === channel && ccNum === c.controllerNumber);\n if (changes !== undefined)\n {\n // this controller is locked, BEGONE CHANGE!\n deleteThisEvent();\n continue;\n }\n // bank maybe?\n if (ccNum === midiControllers.bankSelect || ccNum === midiControllers.lsbForControl0BankSelect)\n {\n if (channelsToChangeProgram.has(channel))\n {\n // BEGONE!\n deleteThisEvent();\n continue;\n }\n }\n break;\n \n case messageTypes.systemExclusive:\n // check for xg on\n if (isXGOn(e))\n {\n SpessaSynthInfo(\"%cXG system on detected\", consoleColors.info);\n system = \"xg\";\n addedGs = true; // flag as true so gs won't get added\n }\n else\n // check for xg program change\n if (\n e.messageData[0] === 0x43 // yamaha\n && e.messageData[2] === 0x4C // XG\n && e.messageData[3] === 0x08 // part parameter\n && e.messageData[5] === 0x03 // program change\n )\n {\n // do we delete it?\n if (channelsToChangeProgram.has(e.messageData[4] + portOffset))\n {\n // this channel has program change. BEGONE!\n deleteThisEvent();\n }\n }\n else\n // check for GS on\n if (isGSOn(e))\n {\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 }\n else\n // check for GM/2 on\n if (isGMOn(e) || isGM2On(e))\n {\n // that's a GM1 system change, remove it!\n SpessaSynthInfo(\n \"%cGM/2 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 {\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 (midi.tracks[0][0].messageStatusByte === messageTypes.trackName)\n {\n index++;\n }\n midi.tracks[0].splice(index, 0, getGsOn(0));\n SpessaSynthInfo(\"%cGS on not detected. Adding it.\", consoleColors.info);\n }\n this.flush();\n SpessaSynthGroupEnd();\n}\n\n/**\n * Modifies the sequence according to the locked presets and controllers in the given snapshot\n * @this {BasicMIDI}\n * @param snapshot {SynthesizerSnapshot}\n */\nexport function applySnapshotToMIDI(snapshot)\n{\n /**\n * @type {{\n * channel: number,\n * keyShift: number\n * }[]}\n */\n const channelsToTranspose = [];\n /**\n * @type {number[]}\n */\n const channelsToClear = [];\n /**\n * @type {{\n * channel: number,\n * program: number,\n * bank: number,\n * isDrum: boolean\n * }[]}\n */\n const programChanges = [];\n /**\n *\n * @type {{\n * channel: number,\n * controllerNumber: number,\n * controllerValue: number\n * }[]}\n */\n const controllerChanges = [];\n snapshot.channelSnapshots.forEach((channel, channelNumber) =>\n {\n if (channel.isMuted)\n {\n channelsToClear.push(channelNumber);\n return;\n }\n const transposeFloat = channel.channelTransposeKeyShift + channel.customControllers[customControllers.channelTransposeFine] / 100;\n if (transposeFloat !== 0)\n {\n channelsToTranspose.push({\n channel: channelNumber,\n keyShift: transposeFloat\n });\n }\n if (channel.lockPreset)\n {\n programChanges.push({\n channel: channelNumber,\n program: channel.program,\n bank: channel.bank,\n isDrum: channel.drumChannel\n });\n }\n // check for locked controllers and change them appropriately\n channel.lockedControllers.forEach((l, ccNumber) =>\n {\n if (!l || ccNumber > 127 || 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 this.modifyMIDI(programChanges, controllerChanges, channelsToClear, channelsToTranspose);\n}", "import { combineArrays, IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { writeRIFFOddSize } from \"../../soundfont/basic_soundfont/riff_chunk.js\";\nimport { getStringBytes, getStringBytesZero } from \"../../utils/byte_functions/string.js\";\nimport { messageTypes, midiControllers, MIDIMessage } from \"../midi_message.js\";\nimport { getGsOn } from \"./midi_editor.js\";\nimport { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../../utils/loggin.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { writeLittleEndian } from \"../../utils/byte_functions/little_endian.js\";\nimport { DEFAULT_PERCUSSION } from \"../../synthetizer/synth_constants.js\";\nimport { chooseBank, isSystemXG, parseBankSelect } from \"../../utils/xg_hacks.js\";\nimport { isGM2On, isGMOn, isGSDrumsOn, isGSOn, isXGOn } from \"../../utils/sysex_detector.js\";\n\n/**\n * @enum {string}\n */\nexport const RMIDINFOChunks = {\n name: \"INAM\",\n album: \"IPRD\",\n album2: \"IALB\",\n artist: \"IART\",\n genre: \"IGNR\",\n picture: \"IPIC\",\n copyright: \"ICOP\",\n creationDate: \"ICRD\",\n comment: \"ICMT\",\n engineer: \"IENG\",\n software: \"ISFT\",\n encoding: \"IENC\",\n midiEncoding: \"MENC\",\n bankOffset: \"DBNK\"\n};\n\nconst FORCED_ENCODING = \"utf-8\";\nconst DEFAULT_COPYRIGHT = \"Created using SpessaSynth\";\n\n/**\n * @typedef {Object} RMIDMetadata\n * @property {string|undefined} name - the name of the file\n * @property {string|undefined} engineer - the engineer who worked on the file\n * @property {string|undefined} artist - the artist\n * @property {string|undefined} album - the album\n * @property {string|undefined} genre - the genre of the song\n * @property {ArrayBuffer|undefined} picture - the image for the file (album cover)\n * @property {string|undefined} comment - the coment of the file\n * @property {string|undefined} creationDate - the creation date of the file\n * @property {string|undefined} copyright - the copyright of the file\n * @property {string|unescape} midiEncoding - the encoding of the inner MIDI file\n */\n\n/**\n * Writes an RMIDI file\n * @this {BasicMIDI}\n * @param soundfontBinary {Uint8Array}\n * @param soundfont {BasicSoundBank}\n * @param bankOffset {number} the bank offset for RMIDI\n * @param encoding {string} the encoding of the RMIDI info chunk\n * @param metadata {RMIDMetadata} the metadata of the file. Optional. If provided, the encoding is forced to utf-8/\n * @param correctBankOffset {boolean}\n * @returns {IndexedByteArray}\n */\nexport function writeRMIDI(\n soundfontBinary,\n soundfont,\n bankOffset = 0,\n encoding = \"Shift_JIS\",\n metadata = {},\n correctBankOffset = true\n)\n{\n const mid = this;\n SpessaSynthGroup(\"%cWriting the RMIDI File...\", consoleColors.info);\n SpessaSynthInfo(\n `%cConfiguration: Bank offset: %c${bankOffset}%c, encoding: %c${encoding}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n SpessaSynthInfo(\"metadata\", metadata);\n SpessaSynthInfo(\"Initial bank offset\", mid.bankOffset);\n if (correctBankOffset)\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 = \"gm\";\n /**\n * The unwanted system messages such as gm/gm2 on\n * @type {{tNum: number, e: MIDIMessage}[]}\n */\n let unwantedSystems = [];\n /**\n * indexes for tracks\n * @type {number[]}\n */\n const eventIndexes = Array(mid.tracks.length).fill(0);\n let remainingTracks = mid.tracks.length;\n \n function findFirstEventIndex()\n {\n let index = 0;\n let ticks = Infinity;\n mid.tracks.forEach((track, i) =>\n {\n if (eventIndexes[i] >= track.length)\n {\n return;\n }\n if (track[eventIndexes[i]].ticks < ticks)\n {\n index = i;\n ticks = track[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(mid.tracks.length).fill(0);\n const channelsAmount = 16 + mid.midiPortChannelOffsets.reduce((max, cur) => cur > max ? cur : max);\n /**\n * @type {{\n * program: number,\n * drums: boolean,\n * lastBank: MIDIMessage,\n * lastBankLSB: MIDIMessage,\n * hasBankSelect: boolean\n * }[]}\n */\n const channelsInfo = [];\n for (let i = 0; i < channelsAmount; i++)\n {\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 {\n let trackNum = findFirstEventIndex();\n const track = mid.tracks[trackNum];\n if (eventIndexes[trackNum] >= track.length)\n {\n remainingTracks--;\n continue;\n }\n const e = track[eventIndexes[trackNum]];\n eventIndexes[trackNum]++;\n \n let portOffset = mid.midiPortChannelOffsets[ports[trackNum]];\n if (e.messageStatusByte === messageTypes.midiPort)\n {\n ports[trackNum] = e.messageData[0];\n continue;\n }\n const status = e.messageStatusByte & 0xF0;\n if (\n status !== messageTypes.controllerChange &&\n status !== messageTypes.programChange &&\n status !== messageTypes.systemExclusive\n )\n {\n continue;\n }\n \n if (status === messageTypes.systemExclusive)\n {\n // check for drum sysex\n if (!isGSDrumsOn(e))\n {\n // check for XG\n if (isXGOn(e))\n {\n system = \"xg\";\n }\n else if (isGSOn(e))\n {\n system = \"gs\";\n }\n else if (isGMOn(e))\n {\n // we do not want gm1\n system = \"gm\";\n unwantedSystems.push({\n tNum: trackNum,\n e: e\n });\n }\n else if (isGM2On(e))\n {\n system = \"gm2\";\n }\n continue;\n }\n const sysexChannel = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15][e.messageData[5] & 0x0F] + portOffset;\n channelsInfo[sysexChannel].drums = !!(e.messageData[7] > 0 && e.messageData[5] >> 4);\n continue;\n }\n \n // program change\n const chNum = (e.messageStatusByte & 0xF) + portOffset;\n /**\n * @type {{program: number, drums: boolean, lastBank: MIDIMessage, lastBankLSB: MIDIMessage, hasBankSelect: boolean}}\n */\n const channel = channelsInfo[chNum];\n if (status === messageTypes.programChange)\n {\n const isXG = isSystemXG(system);\n // check if the preset for this program exists\n const initialProgram = e.messageData[0];\n if (channel.drums)\n {\n if (soundfont.presets.findIndex(p => p.program === initialProgram && p.isDrumPreset(\n isXG,\n true\n )) === -1)\n {\n // doesn't exist. pick any preset that has bank 128.\n e.messageData[0] = soundfont.presets.find(p => p.isDrumPreset(isXG))?.program || 0;\n SpessaSynthInfo(\n `%cNo drum preset %c${initialProgram}%c. Channel %c${chNum}%c. Changing program to ${e.messageData[0]}.`,\n consoleColors.info,\n consoleColors.unrecognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n }\n }\n else\n {\n if (soundfont.presets.findIndex(p => p.program === initialProgram && !p.isDrumPreset(isXG)) === -1)\n {\n // doesn't exist. pick any preset that does not have bank 128.\n e.messageData[0] = soundfont.presets.find(p => !p.isDrumPreset(isXG))?.program || 0;\n SpessaSynthInfo(\n `%cNo preset %c${initialProgram}%c. Channel %c${chNum}%c. Changing program to ${e.messageData[0]}.`,\n consoleColors.info,\n consoleColors.unrecognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n }\n }\n channel.program = e.messageData[0];\n // check if this preset exists for program and bank\n const realBank = Math.max(0, channel.lastBank?.messageData[1] - mid.bankOffset); // make sure to take the previous bank offset into account\n const bankLSB = (channel?.lastBankLSB?.messageData[1] - mid.bankOffset) || 0;\n if (channel.lastBank === undefined)\n {\n continue;\n }\n // adjust bank for XG\n let bank = chooseBank(realBank, bankLSB, channel.drums, isXG);\n if (soundfont.presets.findIndex(p => p.bank === bank && p.program === e.messageData[0]) === -1)\n {\n // no preset with this bank. find this program with any bank\n const targetBank = (soundfont.presets.find(p => p.program === e.messageData[0])?.bank + bankOffset) || bankOffset;\n channel.lastBank.messageData[1] = targetBank;\n if (channel?.lastBankLSB?.messageData)\n {\n channel.lastBankLSB.messageData[1] = targetBank;\n }\n SpessaSynthInfo(\n `%cNo preset %c${bank}:${e.messageData[0]}%c. Channel %c${chNum}%c. Changing bank to ${targetBank}.`,\n consoleColors.info,\n consoleColors.unrecognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n }\n else\n {\n // There is a preset with this bank. Add offset. For drums add the normal offset.\n let drumBank = bank;\n if (isSystemXG(system) && bank === 128)\n {\n bank = 127;\n }\n const newBank = (bank === 128 ? 128 : drumBank) + bankOffset;\n channel.lastBank.messageData[1] = newBank;\n if (channel?.lastBankLSB?.messageData && !channel.drums)\n {\n channel.lastBankLSB.messageData[1] = channel.lastBankLSB.messageData[1] - mid.bankOffset + bankOffset;\n }\n SpessaSynthInfo(\n `%cPreset %c${bank}:${e.messageData[0]}%c exists. Channel %c${chNum}%c. Changing bank to ${newBank}.`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n }\n continue;\n }\n \n // controller change\n // we only care about bank-selects\n const isLSB = e.messageData[0] === midiControllers.lsbForControl0BankSelect;\n if (e.messageData[0] !== midiControllers.bankSelect && !isLSB)\n {\n continue;\n }\n // bank select\n channel.hasBankSelect = true;\n const bankNumber = e.messageData[1];\n // interpret\n const intepretation = parseBankSelect(\n channel?.lastBank?.messageData[1] || 0,\n bankNumber,\n system,\n isLSB,\n channel.drums,\n chNum\n );\n if (intepretation.drumsStatus === 2)\n {\n channel.drums = true;\n }\n else if (intepretation.drumsStatus === 1)\n {\n channel.drums = false;\n }\n if (isLSB)\n {\n channel.lastBankLSB = e;\n }\n else\n {\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 {\n if (has.hasBankSelect === true)\n {\n return;\n }\n // find the first program change (for the given channel)\n const midiChannel = ch % 16;\n const status = messageTypes.programChange | midiChannel;\n // find track with this channel being used\n const portOffset = Math.floor(ch / 16) * 16;\n const port = mid.midiPortChannelOffsets.indexOf(portOffset);\n const track = mid.tracks.find((t, tNum) => mid.midiPorts[tNum] === port && mid.usedChannelsOnTrack[tNum].has(\n midiChannel));\n if (track === undefined)\n {\n // this channel is not used at all\n return;\n }\n let indexToAdd = track.findIndex(e => e.messageStatusByte === status);\n if (indexToAdd === -1)\n {\n // no program change...\n // add programs if they are missing from the track\n // (need them to activate bank 1 for the embedded sfont)\n const programIndex = track.findIndex(e => (e.messageStatusByte > 0x80 && e.messageStatusByte < 0xF0) && (e.messageStatusByte & 0xF) === midiChannel);\n if (programIndex === -1)\n {\n // no voices??? skip\n return;\n }\n const programTicks = track[programIndex].ticks;\n const targetProgram = soundfont.getPreset(0, 0).program;\n track.splice(programIndex, 0, new MIDIMessage(\n programTicks,\n messageTypes.programChange | midiChannel,\n new IndexedByteArray([targetProgram])\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[indexToAdd].ticks;\n const targetBank = (soundfont.getPreset(\n 0,\n has.program,\n isSystemXG(system)\n )?.bank + bankOffset) || bankOffset;\n track.splice(indexToAdd, 0, new MIDIMessage(\n ticks,\n messageTypes.controllerChange | midiChannel,\n new IndexedByteArray([midiControllers.bankSelect, targetBank])\n ));\n });\n \n // make sure to put xg if gm\n if (system !== \"gs\" && !isSystemXG(system))\n {\n for (const m of unwantedSystems)\n {\n mid.tracks[m.tNum].splice(mid.tracks[m.tNum].indexOf(m.e), 1);\n }\n let index = 0;\n if (mid.tracks[0][0].messageStatusByte === messageTypes.trackName)\n {\n index++;\n }\n mid.tracks[0].splice(index, 0, getGsOn(0));\n }\n }\n const newMid = new IndexedByteArray(mid.writeMIDI().buffer);\n \n // info data for RMID\n /**\n * @type {Uint8Array[]}\n */\n const infoContent = [getStringBytes(\"INFO\")];\n const encoder = new TextEncoder();\n // software (SpessaSynth)\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.software, encoder.encode(\"SpessaSynth\"), true)\n );\n // name\n if (metadata.name !== undefined)\n {\n \n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.name, encoder.encode(metadata.name), true)\n );\n encoding = FORCED_ENCODING;\n }\n else\n {\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.name, mid.rawMidiName, true)\n );\n }\n // creation date\n if (metadata.creationDate !== undefined)\n {\n encoding = FORCED_ENCODING;\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.creationDate, encoder.encode(metadata.creationDate), true)\n );\n }\n else\n {\n const today = new Date().toLocaleString(undefined, {\n weekday: \"long\",\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\"\n });\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.creationDate, getStringBytesZero(today), true)\n );\n }\n // comment\n if (metadata.comment !== undefined)\n {\n encoding = FORCED_ENCODING;\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.comment, encoder.encode(metadata.comment))\n );\n }\n // engineer\n if (metadata.engineer !== undefined)\n {\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.engineer, encoder.encode(metadata.engineer), true)\n );\n }\n // album\n if (metadata.album !== undefined)\n {\n // note that there are two album chunks: IPRD and IALB\n encoding = FORCED_ENCODING;\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.album, encoder.encode(metadata.album), true)\n );\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.album2, encoder.encode(metadata.album), true)\n );\n }\n // artist\n if (metadata.artist !== undefined)\n {\n encoding = FORCED_ENCODING;\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.artist, encoder.encode(metadata.artist), true)\n );\n }\n // genre\n if (metadata.genre !== undefined)\n {\n encoding = FORCED_ENCODING;\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.genre, encoder.encode(metadata.genre), true)\n );\n }\n // picture\n if (metadata.picture !== undefined)\n {\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.picture, new Uint8Array(metadata.picture))\n );\n }\n // copyright\n if (metadata.copyright !== undefined)\n {\n encoding = FORCED_ENCODING;\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.copyright, encoder.encode(metadata.copyright), true)\n );\n }\n else\n {\n // use midi copyright if possible\n const copyright = mid.copyright.length > 0 ? mid.copyright : DEFAULT_COPYRIGHT;\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.copyright, getStringBytesZero(copyright))\n );\n }\n \n // bank offset\n const DBNK = new IndexedByteArray(2);\n writeLittleEndian(DBNK, bankOffset, 2);\n infoContent.push(writeRIFFOddSize(RMIDINFOChunks.bankOffset, DBNK));\n // midi encoding\n if (metadata.midiEncoding !== undefined)\n {\n infoContent.push(\n writeRIFFOddSize(RMIDINFOChunks.midiEncoding, encoder.encode(metadata.midiEncoding))\n );\n encoding = FORCED_ENCODING;\n }\n // encoding\n infoContent.push(writeRIFFOddSize(RMIDINFOChunks.encoding, getStringBytesZero(encoding)));\n \n // combine and write out\n const infodata = combineArrays(infoContent);\n const rmiddata = combineArrays([\n getStringBytes(\"RMID\"),\n writeRIFFOddSize(\n \"data\",\n newMid\n ),\n writeRIFFOddSize(\n \"LIST\",\n infodata\n ),\n soundfontBinary\n ]);\n SpessaSynthInfo(\"%cFinished!\", consoleColors.info);\n SpessaSynthGroupEnd();\n return writeRIFFOddSize(\n \"RIFF\",\n rmiddata\n );\n}", "import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../../utils/loggin.js\";\nimport { consoleColors } from \"../../utils/other.js\";\nimport { messageTypes, midiControllers } from \"../midi_message.js\";\nimport { DEFAULT_PERCUSSION } from \"../../synthetizer/synth_constants.js\";\nimport { chooseBank, isSystemXG, parseBankSelect } from \"../../utils/xg_hacks.js\";\nimport { isGSDrumsOn, isXGOn } from \"../../utils/sysex_detector.js\";\n\n/**\n * Gets the used programs and keys for this MIDI file with a given sound bank\n * @this {BasicMIDI}\n * @param soundfont {BasicSoundBank|SoundFontManager} - the sound bank\n * @returns {Object<string, Set<string>>} Object<bank:program, Set<key-velocity>>\n */\nexport function getUsedProgramsAndKeys(soundfont)\n{\n const mid = this;\n SpessaSynthGroupCollapsed(\n \"%cSearching for all used programs and keys...\",\n consoleColors.info\n );\n // Find every bank:program combo and every key:velocity for each. Make sure to care about ports and drums\n const channelsAmount = 16 + mid.midiPortChannelOffsets.reduce((max, cur) => cur > max ? cur : max);\n /**\n * @type {{program: number, bank: number, bankLSB: number, drums: boolean, string: string, actualBank: number}[]}\n */\n const channelPresets = [];\n for (let i = 0; i < channelsAmount; i++)\n {\n const bank = i % 16 === DEFAULT_PERCUSSION ? 128 : 0;\n channelPresets.push({\n program: 0,\n bank: bank,\n bankLSB: 0,\n actualBank: bank,\n drums: i % 16 === DEFAULT_PERCUSSION, // drums appear on 9 every 16 channels,\n string: `${bank}:0`\n });\n }\n \n // check for xg\n let system = \"gs\";\n \n function updateString(ch)\n {\n const bank = chooseBank(ch.bank, ch.bankLSB, ch.drums, isSystemXG(system));\n // check if this exists in the soundfont\n let exists = soundfont.getPreset(bank, ch.program, isSystemXG(system));\n ch.actualBank = exists.bank;\n ch.program = exists.program;\n ch.string = ch.actualBank + \":\" + ch.program;\n if (!usedProgramsAndKeys[ch.string])\n {\n SpessaSynthInfo(\n `%cDetected a new preset: %c${ch.string}`,\n consoleColors.info,\n consoleColors.recognized\n );\n usedProgramsAndKeys[ch.string] = new Set();\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 * @type {Object<string, Set<string>>}\n */\n const usedProgramsAndKeys = {};\n \n /**\n * indexes for tracks\n * @type {number[]}\n */\n const eventIndexes = Array(mid.tracks.length).fill(0);\n let remainingTracks = mid.tracks.length;\n \n function findFirstEventIndex()\n {\n let index = 0;\n let ticks = Infinity;\n mid.tracks.forEach((track, i) =>\n {\n if (eventIndexes[i] >= track.length)\n {\n return;\n }\n if (track[eventIndexes[i]].ticks < ticks)\n {\n index = i;\n ticks = track[eventIndexes[i]].ticks;\n }\n });\n return index;\n }\n \n const ports = mid.midiPorts.slice();\n // initialize\n channelPresets.forEach(c =>\n {\n updateString(c);\n });\n while (remainingTracks > 0)\n {\n let trackNum = findFirstEventIndex();\n const track = mid.tracks[trackNum];\n if (eventIndexes[trackNum] >= track.length)\n {\n remainingTracks--;\n continue;\n }\n const event = track[eventIndexes[trackNum]];\n eventIndexes[trackNum]++;\n \n if (event.messageStatusByte === messageTypes.midiPort)\n {\n ports[trackNum] = event.messageData[0];\n continue;\n }\n const status = event.messageStatusByte & 0xF0;\n if (\n status !== messageTypes.noteOn &&\n status !== messageTypes.controllerChange &&\n status !== messageTypes.programChange &&\n status !== messageTypes.systemExclusive\n )\n {\n continue;\n }\n const channel = (event.messageStatusByte & 0xF) + mid.midiPortChannelOffsets[ports[trackNum]] || 0;\n let ch = channelPresets[channel];\n switch (status)\n {\n case messageTypes.programChange:\n ch.program = event.messageData[0];\n updateString(ch);\n break;\n \n case messageTypes.controllerChange:\n const isLSB = event.messageData[0] === midiControllers.lsbForControl0BankSelect;\n if (event.messageData[0] !== midiControllers.bankSelect && !isLSB)\n {\n // we only care about bank select\n continue;\n }\n if (system === \"gs\" && ch.drums)\n {\n // gs drums get changed via sysex, ignore here\n continue;\n }\n const bank = event.messageData[1];\n const realBank = Math.max(0, bank - mid.bankOffset);\n if (isLSB)\n {\n ch.bankLSB = realBank;\n }\n else\n {\n ch.bank = realBank;\n }\n // interpret the bank\n const intepretation = parseBankSelect(\n ch.bank,\n realBank,\n system,\n isLSB,\n ch.drums,\n channel\n );\n switch (intepretation.drumsStatus)\n {\n case 0:\n // no change\n break;\n \n case 1:\n // drums changed to off\n // drum change is a program change\n ch.drums = false;\n updateString(ch);\n break;\n \n case 2:\n // drums changed to on\n // drum change is a program change\n ch.drums = true;\n updateString(ch);\n break;\n }\n // do not update the data, bank change doesn't change the preset\n break;\n \n case messageTypes.noteOn:\n if (event.messageData[1] === 0)\n {\n // that's a note off\n continue;\n }\n usedProgramsAndKeys[ch.string].add(`${event.messageData[0]}-${event.messageData[1]}`);\n break;\n \n case messageTypes.systemExclusive:\n // check for drum sysex\n if (!isGSDrumsOn(event))\n {\n // check for XG\n if (isXGOn(event))\n {\n system = \"xg\";\n SpessaSynthInfo(\n \"%cXG on detected!\",\n consoleColors.recognized\n );\n }\n continue;\n }\n const sysexChannel = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15][event.messageData[5] & 0x0F] + mid.midiPortChannelOffsets[ports[trackNum]];\n const isDrum = !!(event.messageData[7] > 0 && event.messageData[5] >> 4);\n ch = channelPresets[sysexChannel];\n ch.drums = isDrum;\n updateString(ch);\n break;\n \n }\n }\n for (const key of Object.keys(usedProgramsAndKeys))\n {\n if (usedProgramsAndKeys[key].size === 0)\n {\n SpessaSynthInfo(\n `%cDetected change but no keys for %c${key}`,\n consoleColors.info,\n consoleColors.value\n );\n delete usedProgramsAndKeys[key];\n }\n }\n SpessaSynthGroupEnd();\n return usedProgramsAndKeys;\n}", "import { IndexedByteArray } from \"../../utils/indexed_array.js\";\nimport { readBytesAsUintBigEndian } from \"../../utils/byte_functions/big_endian.js\";\nimport { DEFAULT_PERCUSSION } from \"../../synthetizer/synth_constants.js\";\n\n/**\n * Calculates all note times in seconds.\n * @this {BasicMIDI}\n * @param minDrumLength {number} the shortest a drum note (channel 10) can be, in seconds.\n * @returns {{\n * midiNote: number,\n * start: number,\n * length: number,\n * velocity: number,\n * }[][]} 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 getNoteTimes(minDrumLength = 0)\n{\n \n /**\n * gets tempo from the midi message\n * @param event {MIDIMessage}\n * @return {number} the tempo in bpm\n */\n function getTempo(event)\n {\n // simulate IndexedByteArray\n event.messageData = new IndexedByteArray(event.messageData.buffer);\n event.messageData.currentIndex = 0;\n return 60000000 / readBytesAsUintBigEndian(event.messageData, 3);\n }\n \n /**\n * an array of 16 arrays (channels)\n * @type {{\n * midiNote: number,\n * start: number,\n * length: number,\n * velocity: number,\n * }[][]}\n */\n const noteTimes = [];\n // flatten and sort by ticks\n const trackData = this.tracks;\n let events = trackData.flat();\n events.sort((e1, e2) => e1.ticks - e2.ticks);\n \n for (let i = 0; i < 16; i++)\n {\n noteTimes.push([]);\n }\n let elapsedTime = 0;\n let oneTickToSeconds = 60 / (120 * this.timeDivision);\n let eventIndex = 0;\n let unfinished = 0;\n /**\n * @type {{\n * midiNote: number,\n * start: number,\n * length: number,\n * velocity: number,\n * }[][]}\n */\n const unfinishedNotes = [];\n for (let i = 0; i < 16; i++)\n {\n unfinishedNotes.push([]);\n }\n const noteOff = (midiNote, channel) =>\n {\n const noteIndex = unfinishedNotes[channel].findIndex(n => n.midiNote === midiNote);\n const note = unfinishedNotes[channel][noteIndex];\n if (note)\n {\n const time = elapsedTime - note.start;\n note.length = time;\n if (channel === DEFAULT_PERCUSSION)\n {\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 {\n const event = events[eventIndex];\n \n const status = event.messageStatusByte >> 4;\n const channel = event.messageStatusByte & 0x0F;\n \n // note off\n if (status === 0x8)\n {\n noteOff(event.messageData[0], channel);\n }\n // note on\n else if (status === 0x9)\n {\n if (event.messageData[1] === 0)\n {\n // never mind, its note off\n noteOff(event.messageData[0], channel);\n }\n else\n {\n // stop previous\n noteOff(event.messageData[0], channel);\n const noteTime = {\n midiNote: event.messageData[0],\n start: elapsedTime,\n length: -1,\n velocity: event.messageData[1] / 127\n };\n noteTimes[channel].push(noteTime);\n unfinishedNotes[channel].push(noteTime);\n unfinished++;\n \n }\n }\n // set tempo\n else if (event.messageStatusByte === 0x51)\n {\n oneTickToSeconds = 60 / (getTempo(event) * this.timeDivision);\n }\n \n if (++eventIndex >= events.length)\n {\n break;\n }\n \n elapsedTime += oneTickToSeconds * (events[eventIndex].ticks - event.ticks);\n }\n \n // finish the unfinished notes\n if (unfinished > 0)\n {\n // for every channel, for every note that is unfinished (has -1 length)\n unfinishedNotes.forEach((channelNotes, channel) =>\n {\n channelNotes.forEach(note =>\n {\n const time = elapsedTime - note.start;\n note.length = time;\n if (channel === DEFAULT_PERCUSSION)\n {\n note.length = time < minDrumLength ? minDrumLength : time;\n }\n });\n });\n }\n return noteTimes;\n}", "// noinspection JSUnusedGlobalSymbols\n\nimport { MIDISequenceData } from \"./midi_sequence.js\";\nimport { getStringBytes, readBytesAsString } from \"../utils/byte_functions/string.js\";\nimport { messageTypes, MIDIMessage } from \"./midi_message.js\";\nimport { readBytesAsUintBigEndian } from \"../utils/byte_functions/big_endian.js\";\nimport { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../utils/loggin.js\";\nimport { consoleColors, formatTitle, sanitizeKarLyrics } from \"../utils/other.js\";\nimport { writeMIDI } from \"./midi_tools/midi_writer.js\";\nimport { applySnapshotToMIDI, modifyMIDI } from \"./midi_tools/midi_editor.js\";\nimport { writeRMIDI } from \"./midi_tools/rmidi_writer.js\";\nimport { getUsedProgramsAndKeys } from \"./midi_tools/used_keys_loaded.js\";\nimport { IndexedByteArray } from \"../utils/indexed_array.js\";\nimport { getNoteTimes } from \"./midi_tools/get_note_times.js\";\n\n/**\n * BasicMIDI is the base of a complete MIDI file, used by the sequencer internally.\n * BasicMIDI is not available on the main thread, as it contains the actual track data which can be large.\n * It can be accessed by calling getMIDI() on the Sequencer.\n */\nclass BasicMIDI extends MIDISequenceData\n{\n \n /**\n * The embedded soundfont in the MIDI file, represented as an ArrayBuffer, if available.\n * @type {ArrayBuffer|undefined}\n */\n embeddedSoundFont = undefined;\n \n /**\n * The actual track data of the MIDI file, represented as an array of tracks.\n * Tracks are arrays of MIDIMessage objects.\n * @type {MIDIMessage[][]}\n */\n tracks = [];\n \n /**\n * If the MIDI file is a DLS RMIDI file.\n * @type {boolean}\n */\n isDLSRMIDI = false;\n \n /**\n * Copies a MIDI\n * @param mid {BasicMIDI}\n * @returns {BasicMIDI}\n */\n static copyFrom(mid)\n {\n const m = new BasicMIDI();\n m._copyFromSequence(mid);\n \n m.isDLSRMIDI = mid.isDLSRMIDI;\n m.embeddedSoundFont = mid.embeddedSoundFont ? mid.embeddedSoundFont.slice(0) : undefined; // Deep copy\n m.tracks = mid.tracks.map(track => [...track]); // Shallow copy of each track array\n \n return m;\n }\n \n /**\n * Parses internal MIDI values\n * @protected\n */\n _parseInternal()\n {\n SpessaSynthGroup(\n \"%cInterpreting MIDI events...\",\n consoleColors.info\n );\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 * @type {boolean}\n */\n let karaokeHasTitle = false;\n \n this.keyRange = { max: 0, min: 127 };\n \n /**\n * Will be joined with \"\\n\" to form the final string\n * @type {string[]}\n */\n let copyrightComponents = [];\n let copyrightDetected = false;\n if (typeof this.RMIDInfo[\"ICOP\"] !== \"undefined\")\n {\n // if RMIDI has copyright info, don't try to detect one.\n copyrightDetected = true;\n }\n \n \n let nameDetected = false;\n if (typeof this.RMIDInfo[\"INAM\"] !== \"undefined\")\n {\n // same as with copyright\n nameDetected = true;\n }\n \n // loop tracking\n let loopStart = null;\n let loopEnd = null;\n \n for (let i = 0; i < this.tracks.length; i++)\n {\n /**\n * @type {MIDIMessage[]}\n */\n const track = this.tracks[i];\n const usedChannels = new Set();\n let trackHasVoiceMessages = false;\n \n for (const e of track)\n {\n // check if it's a voice message\n if (e.messageStatusByte >= 0x80 && e.messageStatusByte < 0xF0)\n {\n trackHasVoiceMessages = true;\n // voice messages are 7-bit always\n for (let j = 0; j < e.messageData.length; j++)\n {\n e.messageData[j] = Math.min(127, e.messageData[j]);\n }\n // last voice event tick\n if (e.ticks > this.lastVoiceEventTick)\n {\n this.lastVoiceEventTick = e.ticks;\n }\n \n // interpret the voice message\n switch (e.messageStatusByte & 0xF0)\n {\n // cc change: loop points\n case messageTypes.controllerChange:\n switch (e.messageData[0])\n {\n case 2:\n case 116:\n loopStart = e.ticks;\n break;\n \n case 4:\n case 117:\n if (loopEnd === null)\n {\n loopEnd = e.ticks;\n }\n else\n {\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 (this.isDLSRMIDI && e.messageData[1] !== 0 && e.messageData[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 messageTypes.noteOn:\n usedChannels.add(e.messageStatusByte & 0x0F);\n const note = e.messageData[0];\n this.keyRange.min = Math.min(this.keyRange.min, note);\n this.keyRange.max = Math.max(this.keyRange.max, note);\n break;\n }\n }\n e.messageData.currentIndex = 0;\n const eventText = readBytesAsString(e.messageData, e.messageData.length);\n e.messageData.currentIndex = 0;\n // interpret the message\n switch (e.messageStatusByte)\n {\n case messageTypes.setTempo:\n // add the tempo change\n e.messageData.currentIndex = 0;\n this.tempoChanges.push({\n ticks: e.ticks,\n tempo: 60000000 / readBytesAsUintBigEndian(e.messageData, 3)\n });\n e.messageData.currentIndex = 0;\n break;\n \n case messageTypes.marker:\n // check for loop markers\n const text = eventText.trim().toLowerCase();\n switch (text)\n {\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 e.messageData.currentIndex = 0;\n break;\n \n case messageTypes.copyright:\n if (!copyrightDetected)\n {\n e.messageData.currentIndex = 0;\n copyrightComponents.push(readBytesAsString(\n e.messageData,\n e.messageData.length,\n undefined,\n false\n ));\n e.messageData.currentIndex = 0;\n }\n break;\n \n case messageTypes.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 (eventText.trim().startsWith(\"@KMIDI KARAOKE FILE\"))\n {\n this.isKaraokeFile = true;\n SpessaSynthInfo(\"%cKaraoke MIDI detected!\", consoleColors.recognized);\n }\n \n if (this.isKaraokeFile)\n {\n // replace the type of the message with text\n e.messageStatusByte = messageTypes.text;\n }\n else\n {\n // add lyrics like a regular midi file\n this.lyrics.push(e.messageData);\n this.lyricsTicks.push(e.ticks);\n break;\n }\n \n // kar: treat the same as text\n // fallthrough\n case messageTypes.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 {\n this.isKaraokeFile = true;\n \n SpessaSynthInfo(\"%cKaraoke MIDI detected!\", consoleColors.recognized);\n }\n else if (this.isKaraokeFile)\n {\n // check for @T (title)\n // or @A because it is a title too sometimes?\n // IDK it's strange\n if (checkedText.startsWith(\"@T\") || checkedText.startsWith(\"@A\"))\n {\n if (!karaokeHasTitle)\n {\n this.midiName = checkedText.substring(2).trim();\n karaokeHasTitle = true;\n nameDetected = true;\n // encode to rawMidiName\n this.rawMidiName = getStringBytes(this.midiName);\n }\n else\n {\n // append to copyright\n copyrightComponents.push(checkedText.substring(2).trim());\n }\n }\n else if (checkedText[0] !== \"@\")\n {\n // non @: the lyrics\n this.lyrics.push(sanitizeKarLyrics(e.messageData));\n this.lyricsTicks.push(e.ticks);\n }\n }\n break;\n \n case messageTypes.trackName:\n break;\n }\n }\n // add used channels\n this.usedChannelsOnTrack.push(usedChannels);\n \n // track name\n this.trackNames[i] = \"\";\n const trackName = track.find(e => e.messageStatusByte === messageTypes.trackName);\n if (trackName)\n {\n trackName.messageData.currentIndex = 0;\n const name = readBytesAsString(trackName.messageData, trackName.messageData.length);\n this.trackNames[i] = name;\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 (!trackHasVoiceMessages)\n {\n copyrightComponents.push(name);\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 {\n const firstNoteOn = t.find(e => (e.messageStatusByte & 0xF0) === messageTypes.noteOn);\n if (firstNoteOn)\n {\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 \n if (loopStart !== null && loopEnd === null)\n {\n // not a loop\n loopStart = this.firstNoteOn;\n loopEnd = this.lastVoiceEventTick;\n }\n else\n {\n if (loopStart === null)\n {\n loopStart = this.firstNoteOn;\n }\n \n if (loopEnd === null || loopEnd === 0)\n {\n loopEnd = this.lastVoiceEventTick;\n }\n }\n \n /**\n *\n * @type {{start: number, end: number}}\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.midiPorts = [];\n this.midiPortChannelOffsets = [];\n for (let trackNum = 0; trackNum < this.tracks.length; trackNum++)\n {\n this.midiPorts.push(-1);\n if (this.usedChannelsOnTrack[trackNum].size === 0)\n {\n continue;\n }\n for (const e of this.tracks[trackNum])\n {\n if (e.messageStatusByte !== messageTypes.midiPort)\n {\n continue;\n }\n const port = e.messageData[0];\n this.midiPorts[trackNum] = port;\n if (this.midiPortChannelOffsets[port] === undefined)\n {\n this.midiPortChannelOffsets[port] = portOffset;\n portOffset += 16;\n }\n }\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 (let port of this.midiPorts)\n {\n if (port !== -1)\n {\n if (defaultPort > port)\n {\n defaultPort = port;\n }\n }\n }\n if (defaultPort === Infinity)\n {\n defaultPort = 0;\n }\n this.midiPorts = this.midiPorts.map(port => port === -1 ? defaultPort : port);\n // add fake port if empty\n if (this.midiPortChannelOffsets.length === 0)\n {\n this.midiPortChannelOffsets = [0];\n }\n if (this.midiPortChannelOffsets.length < 2)\n {\n SpessaSynthInfo(`%cNo additional MIDI Ports detected.`, consoleColors.info);\n }\n else\n {\n this.isMultiPort = true;\n SpessaSynthInfo(`%cMIDI Ports detected!`, consoleColors.recognized);\n }\n \n // midi name\n if (!nameDetected)\n {\n if (this.tracks.length > 1)\n {\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].find(\n message => message.messageStatusByte >= messageTypes.noteOn\n &&\n message.messageStatusByte < messageTypes.polyPressure\n ) === undefined\n )\n {\n \n let name = this.tracks[0].find(message => message.messageStatusByte === messageTypes.trackName);\n if (name)\n {\n this.rawMidiName = name.messageData;\n name.messageData.currentIndex = 0;\n this.midiName = readBytesAsString(name.messageData, name.messageData.length, undefined, false);\n }\n }\n }\n else\n {\n // if only 1 track, find the first \"track name\" event\n let name = this.tracks[0].find(message => message.messageStatusByte === messageTypes.trackName);\n if (name)\n {\n this.rawMidiName = name.messageData;\n name.messageData.currentIndex = 0;\n this.midiName = readBytesAsString(name.messageData, name.messageData.length, undefined, false);\n }\n }\n }\n \n if (!copyrightDetected)\n {\n this.copyright = copyrightComponents\n // trim and group newlines into one\n .map(c => c.trim().replace(/(\\r?\\n)+/g, \"\\n\"))\n // remove empty strings\n .filter(c => c.length > 0)\n // join with newlines\n .join(\"\\n\") || \"\";\n }\n \n this.midiName = this.midiName.trim();\n this.midiNameUsesFileName = false;\n // if midiName is \"\", use the file name\n if (this.midiName.length === 0)\n {\n SpessaSynthInfo(\n `%cNo name detected. Using the alt name!`,\n consoleColors.info\n );\n this.midiName = formatTitle(this.fileName);\n this.midiNameUsesFileName = true;\n // encode it too\n this.rawMidiName = new Uint8Array(this.midiName.length);\n for (let i = 0; i < this.midiName.length; i++)\n {\n this.rawMidiName[i] = this.midiName.charCodeAt(i);\n }\n }\n else\n {\n SpessaSynthInfo(\n `%cMIDI Name detected! %c\"${this.midiName}\"`,\n consoleColors.info,\n consoleColors.recognized\n );\n }\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[0].ticks === 0))\n {\n const track = this.tracks[0];\n // can copy\n track.unshift(new MIDIMessage(\n 0,\n messageTypes.trackName,\n new IndexedByteArray(this.rawMidiName.buffer)\n ));\n }\n \n \n /**\n * The total playback time, in seconds\n * @type {number}\n */\n this.duration = this.MIDIticksToSeconds(this.lastVoiceEventTick);\n \n SpessaSynthInfo(\"%cSuccess!\", consoleColors.recognized);\n SpessaSynthGroupEnd();\n }\n \n /**\n * Updates all internal values\n */\n flush()\n {\n \n for (const t of this.tracks)\n {\n // sort the track by ticks\n t.sort((e1, e2) => e1.ticks - e2.ticks);\n }\n this._parseInternal();\n }\n}\n\nBasicMIDI.prototype.writeMIDI = writeMIDI;\nBasicMIDI.prototype.modifyMIDI = modifyMIDI;\nBasicMIDI.prototype.applySnapshotToMIDI = applySnapshotToMIDI;\nBasicMIDI.prototype.writeRMIDI = writeRMIDI;\nBasicMIDI.prototype.getUsedProgramsAndKeys = getUsedProgramsAndKeys;\nBasicMIDI.prototype.getNoteTimes = getNoteTimes;\n\nexport { BasicMIDI };", "import { consoleColors, formatTime } from \"../utils/other.js\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo, SpessaSynthWarn } from \"../utils/loggin.js\";\nimport { BasicMIDI } from \"../midi/basic_midi.js\";\n\n/**\n * @param trackNum {number}\n * @param port {number}\n * @this {SpessaSynthSequencer}\n */\nexport function assignMIDIPort(trackNum, port)\n{\n // do not assign ports to empty tracks\n if (this.midiData.usedChannelsOnTrack[trackNum].size === 0)\n {\n return;\n }\n \n // assign new 16 channels if the port is not occupied yet\n if (this.midiPortChannelOffset === 0)\n {\n this.midiPortChannelOffset += 16;\n this.midiPortChannelOffsets[port] = 0;\n }\n \n if (this.midiPortChannelOffsets[port] === undefined)\n {\n if (this.synth.midiAudioChannels.length < this.midiPortChannelOffset + 15)\n {\n this._addNewMidiPort();\n }\n this.midiPortChannelOffsets[port] = this.midiPortChannelOffset;\n this.midiPortChannelOffset += 16;\n }\n \n this.midiPorts[trackNum] = port;\n}\n\n/**\n * Loads a new sequence\n * @param parsedMidi {BasicMIDI}\n * @param autoPlay {boolean}\n * @this {SpessaSynthSequencer}\n * @private\n */\nexport function loadNewSequence(parsedMidi, autoPlay = true)\n{\n this.stop();\n if (!parsedMidi.tracks)\n {\n throw new Error(\"This MIDI has no tracks!\");\n }\n \n this.oneTickToSeconds = 60 / (120 * parsedMidi.timeDivision);\n \n /**\n * @type {BasicMIDI}\n */\n this.midiData = parsedMidi;\n \n // check for embedded soundfont\n if (this.midiData.embeddedSoundFont !== undefined)\n {\n SpessaSynthInfo(\"%cEmbedded soundfont detected! Using it.\", consoleColors.recognized);\n this.synth.setEmbeddedSoundFont(this.midiData.embeddedSoundFont, this.midiData.bankOffset);\n }\n else\n {\n if (this.synth.overrideSoundfont)\n {\n // clean up the embedded soundfont\n this.synth.clearSoundFont(true, true);\n }\n SpessaSynthGroupCollapsed(\"%cPreloading samples...\", consoleColors.info);\n // smart preloading: load only samples used in the midi!\n const used = this.midiData.getUsedProgramsAndKeys(this.synth.soundfontManager);\n for (const [programBank, combos] of Object.entries(used))\n {\n const bank = parseInt(programBank.split(\":\")[0]);\n const program = parseInt(programBank.split(\":\")[1]);\n const preset = this.synth.getPreset(bank, program);\n SpessaSynthInfo(\n `%cPreloading used samples on %c${preset.presetName}%c...`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n for (const combo of combos)\n {\n const split = combo.split(\"-\");\n preset.preloadSpecific(parseInt(split[0]), parseInt(split[1]));\n }\n }\n SpessaSynthGroupEnd();\n }\n \n /**\n * the midi track data\n * @type {MIDIMessage[][]}\n */\n this.tracks = this.midiData.tracks;\n \n // copy over the port data\n this.midiPorts = this.midiData.midiPorts.slice();\n \n // clear last port data\n this.midiPortChannelOffset = 0;\n this.midiPortChannelOffsets = {};\n // assign port offsets\n this.midiData.midiPorts.forEach((port, trackIndex) =>\n {\n this.assignMIDIPort(trackIndex, port);\n });\n \n /**\n * Same as \"audio.duration\" property (seconds)\n * @type {number}\n */\n this.duration = this.midiData.duration;\n this.firstNoteTime = this.midiData.MIDIticksToSeconds(this.midiData.firstNoteOn);\n SpessaSynthInfo(`%cTotal song time: ${formatTime(Math.ceil(this.duration)).time}`, consoleColors.recognized);\n this?.onSongChange?.(this.songIndex, autoPlay);\n \n if (this.duration <= 1)\n {\n SpessaSynthWarn(\n `%cVery short song: (${formatTime(Math.round(this.duration)).time}). Disabling loop!`,\n consoleColors.warn\n );\n this.loop = false;\n }\n if (autoPlay)\n {\n this.play(true);\n }\n else\n {\n // this shall not play: play to the first note and then wait\n const targetTime = this.skipToFirstNoteOn ? this.midiData.firstNoteOn - 1 : 0;\n this.setTimeTicks(targetTime);\n this.pause();\n }\n}\n\n/**\n * @param midiBuffers {BasicMIDI[]}\n * @param autoPlay {boolean}\n * @this {SpessaSynthSequencer}\n */\nexport function loadNewSongList(midiBuffers, autoPlay = true)\n{\n /**\n * parse the MIDIs (only the array buffers, MIDI is unchanged)\n * @type {BasicMIDI[]}\n */\n this.songs = midiBuffers.map(m => BasicMIDI.copyFrom(m));\n if (this.songs.length < 1)\n {\n return;\n }\n this.songIndex = 0;\n if (this.songs.length > 1)\n {\n this.loop = false;\n }\n this.shuffleSongIndexes();\n this?.onSongListChange?.(this.songs);\n this.loadCurrentSong(autoPlay);\n}\n\n/**\n * @this {SpessaSynthSequencer}\n */\nexport function nextSong()\n{\n if (this.songs.length === 1)\n {\n this.currentTime = 0;\n return;\n }\n this.songIndex++;\n this.songIndex %= this.songs.length;\n this.loadCurrentSong();\n}\n\n/**\n * @this {SpessaSynthSequencer}\n */\nexport function previousSong()\n{\n if (this.songs.length === 1)\n {\n this.currentTime = 0;\n return;\n }\n this.songIndex--;\n if (this.songIndex < 0)\n {\n this.songIndex = this.songs.length - 1;\n }\n this.loadCurrentSong();\n}", "import { getEvent, messageTypes, midiControllers } from \"../midi/midi_message.js\";\nimport { resetArray } from \"../synthetizer/audio_engine/engine_components/controller_tables.js\";\nimport { nonResetableCCs } from \"../synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js\";\n\n\n// an array with preset default values\nconst defaultControllerArray = resetArray.slice(0, 128);\n\n/**\n * plays from start to the target time, excluding note messages (to get the synth to the correct state)\n * @private\n * @param time {number} in seconds\n * @param ticks {number} optional MIDI ticks, when given is used instead of time\n * @returns {boolean} true if the midi file is not finished\n * @this {SpessaSynthSequencer}\n */\nexport function _playTo(time, ticks = undefined)\n{\n this.oneTickToSeconds = 60 / (120 * this.midiData.timeDivision);\n // reset\n this.synth.resetAllControllers();\n this.sendMIDIReset();\n this._resetTimers();\n \n const channelsToSave = this.synth.midiAudioChannels.length;\n /**\n * save pitch bends here and send them only after\n * @type {number[]}\n */\n const pitchBends = Array(channelsToSave).fill(8192);\n \n /**\n * Save programs here and send them only after\n * @type {{program: number, bank: number, actualBank: number}[]}\n */\n const programs = [];\n for (let i = 0; i < channelsToSave; i++)\n {\n programs.push({\n program: -1,\n bank: 0,\n actualBank: 0\n });\n }\n \n const isCCNonSkippable = controllerNumber => (\n controllerNumber === midiControllers.dataDecrement ||\n controllerNumber === midiControllers.dataIncrement ||\n controllerNumber === midiControllers.dataEntryMsb ||\n controllerNumber === midiControllers.dataDecrement ||\n controllerNumber === midiControllers.lsbForControl6DataEntry ||\n controllerNumber === midiControllers.RPNLsb ||\n controllerNumber === midiControllers.RPNMsb ||\n controllerNumber === midiControllers.NRPNLsb ||\n controllerNumber === midiControllers.NRPNMsb ||\n controllerNumber === midiControllers.bankSelect ||\n controllerNumber === midiControllers.lsbForControl0BankSelect ||\n controllerNumber === midiControllers.resetAllControllers\n );\n \n /**\n * Save controllers here and send them only after\n * @type {number[][]}\n */\n const savedControllers = [];\n for (let i = 0; i < channelsToSave; i++)\n {\n savedControllers.push(Array.from(defaultControllerArray));\n }\n \n /**\n * RP-15 compliant reset\n * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf\n * @param chan {number}\n */\n function resetAllControlllers(chan)\n {\n // reset pitch bend\n pitchBends[chan] = 8192;\n if (savedControllers?.[chan] === undefined)\n {\n return;\n }\n for (let i = 0; i < defaultControllerArray.length; i++)\n {\n if (!nonResetableCCs.has(i))\n {\n savedControllers[chan][i] = defaultControllerArray[i];\n }\n }\n }\n \n while (true)\n {\n // find the next event\n let trackIndex = this._findFirstEventIndex();\n let event = this.tracks[trackIndex][this.eventIndex[trackIndex]];\n if (ticks !== undefined)\n {\n if (event.ticks >= ticks)\n {\n break;\n }\n }\n else\n {\n if (this.playedTime >= time)\n {\n break;\n }\n }\n \n // skip note ons\n const info = getEvent(event.messageStatusByte);\n // Keep in mind midi ports to determine the channel!\n const channel = info.channel + (this.midiPortChannelOffsets[this.midiPorts[trackIndex]] || 0);\n switch (info.status)\n {\n // skip note messages\n case messageTypes.noteOn:\n // track portamento control as last note\n if (savedControllers[channel] === undefined)\n {\n savedControllers[channel] = Array.from(defaultControllerArray);\n }\n savedControllers[channel][midiControllers.portamentoControl] = event.messageData[0];\n break;\n \n case messageTypes.noteOff:\n break;\n \n // skip pitch bend\n case messageTypes.pitchBend:\n pitchBends[channel] = event.messageData[1] << 7 | event.messageData[0];\n break;\n \n case messageTypes.programChange:\n // empty tracks cannot program change\n if (this.midiData.isMultiPort && this.midiData.usedChannelsOnTrack[trackIndex].size === 0)\n {\n break;\n }\n const p = programs[channel];\n p.program = event.messageData[0];\n p.actualBank = p.bank;\n break;\n \n case messageTypes.controllerChange:\n // empty tracks cannot controller change\n if (this.midiData.isMultiPort && this.midiData.usedChannelsOnTrack[trackIndex].size === 0)\n {\n break;\n }\n // do not skip data entries\n const controllerNumber = event.messageData[0];\n if (isCCNonSkippable(controllerNumber))\n {\n let ccV = event.messageData[1];\n if (controllerNumber === midiControllers.bankSelect)\n {\n // add the bank to be saved\n programs[channel].bank = ccV;\n break;\n }\n else if (controllerNumber === midiControllers.resetAllControllers)\n {\n resetAllControlllers(channel);\n }\n if (this.sendMIDIMessages)\n {\n this.sendMIDICC(channel, controllerNumber, ccV);\n }\n else\n {\n this.synth.controllerChange(channel, controllerNumber, ccV);\n }\n }\n else\n {\n if (savedControllers[channel] === undefined)\n {\n savedControllers[channel] = Array.from(defaultControllerArray);\n }\n savedControllers[channel][controllerNumber] = event.messageData[1];\n }\n break;\n \n default:\n this._processEvent(event, trackIndex);\n break;\n }\n \n this.eventIndex[trackIndex]++;\n // find the next event\n trackIndex = this._findFirstEventIndex();\n let nextEvent = this.tracks[trackIndex][this.eventIndex[trackIndex]];\n if (nextEvent === undefined)\n {\n this.stop();\n return false;\n }\n this.playedTime += this.oneTickToSeconds * (nextEvent.ticks - event.ticks);\n }\n \n // restoring saved controllers\n if (this.sendMIDIMessages)\n {\n for (let channelNumber = 0; channelNumber < channelsToSave; channelNumber++)\n {\n // restore pitch bends\n if (pitchBends[channelNumber] !== undefined)\n {\n this.sendMIDIPitchWheel(\n channelNumber,\n pitchBends[channelNumber] >> 7,\n pitchBends[channelNumber] & 0x7F\n );\n }\n if (savedControllers[channelNumber] !== undefined)\n {\n // every controller that has changed\n savedControllers[channelNumber].forEach((value, index) =>\n {\n if (value !== defaultControllerArray[index] && !isCCNonSkippable(\n index))\n {\n this.sendMIDICC(channelNumber, index, value);\n }\n });\n }\n // restore programs\n if (programs[channelNumber].program >= 0 && programs[channelNumber].actualBank >= 0)\n {\n const bank = programs[channelNumber].actualBank;\n this.sendMIDICC(channelNumber, midiControllers.bankSelect, bank);\n this.sendMIDIProgramChange(channelNumber, programs[channelNumber].program);\n }\n }\n }\n else\n {\n // for all synth channels\n for (let channelNumber = 0; channelNumber < channelsToSave; channelNumber++)\n {\n // restore pitch bends\n if (pitchBends[channelNumber] !== undefined)\n {\n this.synth.pitchWheel(channelNumber, pitchBends[channelNumber] >> 7, pitchBends[channelNumber] & 0x7F);\n }\n if (savedControllers[channelNumber] !== undefined)\n {\n // every controller that has changed\n savedControllers[channelNumber].forEach((value, index) =>\n {\n if (value !== defaultControllerArray[index] && !isCCNonSkippable(\n index))\n {\n this.synth.controllerChange(\n channelNumber,\n index,\n value\n );\n }\n });\n }\n // restore programs\n if (programs[channelNumber].program >= 0 && programs[channelNumber].actualBank >= 0)\n {\n const bank = programs[channelNumber].actualBank;\n this.synth.controllerChange(channelNumber, midiControllers.bankSelect, bank);\n this.synth.programChange(channelNumber, programs[channelNumber].program);\n }\n }\n }\n return true;\n}\n\n/**\n * Starts the playback\n * @param resetTime {boolean} If true, time is set to 0 s\n * @this {SpessaSynthSequencer}\n */\nexport function play(resetTime = false)\n{\n if (this.midiData === undefined)\n {\n return;\n }\n \n // reset the time if necessary\n if (resetTime)\n {\n this.pausedTime = undefined;\n this.currentTime = 0;\n return;\n }\n \n if (this.currentTime >= this.duration)\n {\n this.pausedTime = undefined;\n this.currentTime = 0;\n return;\n }\n \n // unpause if paused\n if (this.paused)\n {\n // adjust the start time\n this._recalculateStartTime(this.pausedTime);\n this.pausedTime = undefined;\n }\n if (!this.sendMIDIMessages)\n {\n this.playingNotes.forEach(n =>\n {\n this.synth.noteOn(n.channel, n.midiNote, n.velocity);\n });\n }\n this.setProcessHandler();\n}\n\n/**\n * @this {SpessaSynthSequencer}\n * @param ticks {number}\n */\nexport function setTimeTicks(ticks)\n{\n this.stop();\n this.playingNotes = [];\n this.pausedTime = undefined;\n this?.onTimeChange?.(this.midiData.MIDIticksToSeconds(ticks));\n const isNotFinished = this._playTo(0, ticks);\n this._recalculateStartTime(this.playedTime);\n if (!isNotFinished)\n {\n return;\n }\n this.play();\n}\n\n/**\n * @param time\n * @private\n * @this {SpessaSynthSequencer}\n */\nexport function _recalculateStartTime(time)\n{\n this.absoluteStartTime = this.synth.currentSynthTime - time / this._playbackRate;\n}", "import { messageTypes, midiControllers } from \"../midi/midi_message.js\";\n\nimport { MIDI_CHANNEL_COUNT } from \"../synthetizer/synth_constants.js\";\n\n/**\n * @param message {number[]}\n * @this {SpessaSynthSequencer}\n */\nexport function sendMIDIMessage(message)\n{\n if (!this.sendMIDIMessages)\n {\n return;\n }\n this?.onMIDIMessage?.(message);\n}\n\n/**\n * @this {SpessaSynthSequencer}\n * @param channel {number}\n * @param type {number}\n * @param value {number}\n */\nexport function sendMIDICC(channel, type, value)\n{\n channel %= 16;\n if (!this.sendMIDIMessages)\n {\n return;\n }\n this.sendMIDIMessage([messageTypes.controllerChange | channel, type, value]);\n}\n\n/**\n * @this {SpessaSynthSequencer}\n * @param channel {number}\n * @param program {number}\n */\nexport function sendMIDIProgramChange(channel, program)\n{\n channel %= 16;\n if (!this.sendMIDIMessages)\n {\n return;\n }\n this.sendMIDIMessage([messageTypes.programChange | channel, program]);\n}\n\n/**\n * Sets the pitch of the given channel\n * @this {SpessaSynthSequencer}\n * @param channel {number} usually 0-15: the channel to change pitch\n * @param MSB {number} SECOND byte of the MIDI pitchWheel message\n * @param LSB {number} FIRST byte of the MIDI pitchWheel message\n */\nexport function sendMIDIPitchWheel(channel, MSB, LSB)\n{\n channel %= 16;\n if (!this.sendMIDIMessages)\n {\n return;\n }\n this.sendMIDIMessage([messageTypes.pitchBend | channel, LSB, MSB]);\n}\n\n/**\n * @this {SpessaSynthSequencer}\n */\nexport function sendMIDIReset()\n{\n if (!this.sendMIDIMessages)\n {\n return;\n }\n this.sendMIDIMessage([messageTypes.reset]);\n for (let ch = 0; ch < MIDI_CHANNEL_COUNT; ch++)\n {\n this.sendMIDIMessage([messageTypes.controllerChange | ch, midiControllers.allSoundOff, 0]);\n this.sendMIDIMessage([messageTypes.controllerChange | ch, midiControllers.resetAllControllers, 0]);\n }\n}", "import { _addNewMidiPort, _processEvent } from \"./process_event.js\";\nimport { _findFirstEventIndex, processTick } from \"./process_tick.js\";\nimport { assignMIDIPort, loadNewSequence, loadNewSongList, nextSong, previousSong } from \"./song_control.js\";\nimport { _playTo, _recalculateStartTime, play, setTimeTicks } from \"./play.js\";\nimport { messageTypes, midiControllers } from \"../midi/midi_message.js\";\nimport { sendMIDICC, sendMIDIMessage, sendMIDIPitchWheel, sendMIDIProgramChange, sendMIDIReset } from \"./events.js\";\nimport { SpessaSynthWarn } from \"../utils/loggin.js\";\n\nimport { MIDI_CHANNEL_COUNT } from \"../synthetizer/synth_constants.js\";\n\nclass SpessaSynthSequencer\n{\n /**\n * All the sequencer's songs\n * @type {BasicMIDI[]}\n */\n songs = [];\n \n /**\n * Current song index\n * @type {number}\n */\n songIndex = 0;\n \n /**\n * shuffled song indexes\n * @type {number[]}\n */\n shuffledSongIndexes = [];\n \n /**\n * the synth to use\n * @type {SpessaSynthProcessor}\n */\n synth;\n \n /**\n * if the sequencer is active\n * @type {boolean}\n */\n isActive = false;\n \n /**\n * If the event should instead be sent back to the main thread instead of synth\n * @type {boolean}\n */\n sendMIDIMessages = false;\n \n /**\n * sequencer's loop count\n * @type {number}\n */\n loopCount = Infinity;\n \n /**\n * event's number in this.events\n * @type {number[]}\n */\n eventIndex = [];\n \n /**\n * tracks the time that has already been played\n * @type {number}\n */\n playedTime = 0;\n \n /**\n * The (relative) time when the sequencer was paused. If it's not paused, then it's undefined.\n * @type {number}\n */\n pausedTime = undefined;\n \n /**\n * Absolute playback startTime, bases on the synth's time\n * @type {number}\n */\n absoluteStartTime = 0;\n /**\n * Currently playing notes (for pausing and resuming)\n * @type {{\n * midiNote: number,\n * channel: number,\n * velocity: number\n * }[]}\n */\n playingNotes = [];\n \n /**\n * controls if the sequencer loops (defaults to true)\n * @type {boolean}\n */\n loop = true;\n \n /**\n * controls if the songs are ordered randomly\n * @type {boolean}\n */\n shuffleMode = false;\n \n /**\n * the current track data\n * @type {BasicMIDI}\n */\n midiData = undefined;\n \n /**\n * midi port number for the corresponding track\n * @type {number[]}\n */\n midiPorts = [];\n midiPortChannelOffset = 0;\n /**\n * stored as:\n * Object<midi port, channel offset>\n * @type {Object<number, number>}\n */\n midiPortChannelOffsets = {};\n \n /**\n * @type {boolean}\n */\n skipToFirstNoteOn = true;\n \n /**\n * If true, seq will stay paused when seeking or changing the playback rate\n * @type {boolean}\n */\n preservePlaybackState = false;\n \n /**\n * Called on a MIDI message if sending MIDI messages is enabled\n * @type {function(message: number[])}\n */\n onMIDIMessage;\n \n /**\n * Called when the time changes\n * @type {function(newTime: number)}\n */\n onTimeChange;\n \n /**\n * Calls when sequencer stops the playback\n * @type {function(isFinished: boolean)}\n */\n onPlaybackStop;\n \n /**\n * Calls after the songs have been processed but before the playback begins\n * @type {function(newSongList: BasicMIDI[])}\n */\n onSongListChange;\n \n /**\n * Calls when the song is changed (for example, in a playlist)\n * @type {function(songIndex: number, autoPlay: boolean)}\n */\n onSongChange;\n \n /**\n * Calls when a meta-event occurs\n * @type {function(e: MIDIMessage, trackIndex: number)}\n */\n onMetaEvent;\n \n /**\n * Calls when the loop count changes (usually decreases)\n * @type {function(count: number)}\n */\n onLoopCountChange;\n \n /**\n * @param spessasynthProcessor {SpessaSynthProcessor}\n */\n constructor(spessasynthProcessor)\n {\n this.synth = spessasynthProcessor;\n this.absoluteStartTime = this.synth.currentSynthTime;\n }\n \n /**\n * Controls the playback's rate\n * @type {number}\n * @private\n */\n _playbackRate = 1;\n \n /**\n * @param value {number}\n */\n set playbackRate(value)\n {\n const time = this.currentTime;\n this._playbackRate = value;\n this.currentTime = time;\n }\n \n get currentTime()\n {\n // return the paused time if it's set to something other than undefined\n if (this.pausedTime !== undefined)\n {\n return this.pausedTime;\n }\n \n return (this.synth.currentSynthTime - this.absoluteStartTime) * this._playbackRate;\n }\n \n set currentTime(time)\n {\n if (time > this.duration || time < 0)\n {\n // time is 0\n if (this.skipToFirstNoteOn)\n {\n this.setTimeTicks(this.midiData.firstNoteOn - 1);\n }\n else\n {\n this.setTimeTicks(0);\n }\n return;\n }\n if (this.skipToFirstNoteOn)\n {\n if (time < this.firstNoteTime)\n {\n this.setTimeTicks(this.midiData.firstNoteOn - 1);\n return;\n }\n }\n this.stop();\n this.playingNotes = [];\n const wasPaused = this.paused && this.preservePlaybackState;\n this.pausedTime = undefined;\n this?.onTimeChange?.(time);\n if (this.midiData.duration === 0)\n {\n SpessaSynthWarn(\"No duration!\");\n this?.onPlaybackStop?.(true);\n return;\n }\n this._playTo(time);\n this._recalculateStartTime(time);\n if (wasPaused)\n {\n this.pause();\n }\n else\n {\n this.play();\n }\n }\n \n /**\n * true if paused, false if playing or stopped\n * @returns {boolean}\n */\n get paused()\n {\n return this.pausedTime !== undefined;\n }\n \n /**\n * Pauses the playback\n * @param isFinished {boolean}\n */\n pause(isFinished = false)\n {\n if (this.paused)\n {\n SpessaSynthWarn(\"Already paused\");\n return;\n }\n this.pausedTime = this.currentTime;\n this.stop();\n this?.onPlaybackStop?.(isFinished);\n }\n \n /**\n * Stops the playback\n */\n stop()\n {\n this.clearProcessHandler();\n // disable sustain\n for (let i = 0; i < 16; i++)\n {\n this.synth.controllerChange(i, midiControllers.sustainPedal, 0);\n }\n this.synth.stopAllChannels();\n if (this.sendMIDIMessages)\n {\n for (let note of this.playingNotes)\n {\n this.sendMIDIMessage([messageTypes.noteOff | (note.channel % 16), note.midiNote]);\n }\n for (let c = 0; c < MIDI_CHANNEL_COUNT; c++)\n {\n this.sendMIDICC(c, midiControllers.allNotesOff, 0);\n }\n }\n }\n \n loadCurrentSong(autoPlay = true)\n {\n let index = this.songIndex;\n if (this.shuffleMode)\n {\n index = this.shuffledSongIndexes[this.songIndex];\n }\n this.loadNewSequence(this.songs[index], autoPlay);\n }\n \n _resetTimers()\n {\n this.playedTime = 0;\n this.eventIndex = Array(this.tracks.length).fill(0);\n }\n \n setProcessHandler()\n {\n this.isActive = true;\n }\n \n clearProcessHandler()\n {\n this.isActive = false;\n }\n \n shuffleSongIndexes()\n {\n const indexes = this.songs.map((_, i) => i);\n this.shuffledSongIndexes = [];\n while (indexes.length > 0)\n {\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\n// Web MIDI sending\nSpessaSynthSequencer.prototype.sendMIDIMessage = sendMIDIMessage;\nSpessaSynthSequencer.prototype.sendMIDIReset = sendMIDIReset;\nSpessaSynthSequencer.prototype.sendMIDICC = sendMIDICC;\nSpessaSynthSequencer.prototype.sendMIDIProgramChange = sendMIDIProgramChange;\nSpessaSynthSequencer.prototype.sendMIDIPitchWheel = sendMIDIPitchWheel;\nSpessaSynthSequencer.prototype.assignMIDIPort = assignMIDIPort;\n\nSpessaSynthSequencer.prototype._processEvent = _processEvent;\nSpessaSynthSequencer.prototype._addNewMidiPort = _addNewMidiPort;\nSpessaSynthSequencer.prototype.processTick = processTick;\nSpessaSynthSequencer.prototype._findFirstEventIndex = _findFirstEventIndex;\n\nSpessaSynthSequencer.prototype.loadNewSequence = loadNewSequence;\nSpessaSynthSequencer.prototype.loadNewSongList = loadNewSongList;\nSpessaSynthSequencer.prototype.nextSong = nextSong;\nSpessaSynthSequencer.prototype.previousSong = previousSong;\n\nSpessaSynthSequencer.prototype.play = play;\nSpessaSynthSequencer.prototype._playTo = _playTo;\nSpessaSynthSequencer.prototype.setTimeTicks = setTimeTicks;\nSpessaSynthSequencer.prototype._recalculateStartTime = _recalculateStartTime;\n\nexport { SpessaSynthSequencer };", "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", "import { readBytesAsString } from \"../utils/byte_functions/string.js\";\nimport { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo, SpessaSynthWarn } from \"../utils/loggin.js\";\nimport { consoleColors } from \"../utils/other.js\";\nimport { readBytesAsUintBigEndian } from \"../utils/byte_functions/big_endian.js\";\nimport { readVariableLengthQuantity } from \"../utils/byte_functions/variable_length_quantity.js\";\nimport { RMIDINFOChunks } from \"./midi_tools/rmidi_writer.js\";\nimport { inflateSync } from \"../externals/fflate/fflate.min.js\";\nimport { IndexedByteArray } from \"../utils/indexed_array.js\";\n\n/**\n * @enum {number}\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};\n\n/**\n * @enum {number}\n */\nconst referenceTypeIds = {\n inLineResource: 1,\n inFileResource: 2,\n inFileNode: 3,\n externalFile: 4,\n externalXMF: 5,\n XMFFileURIandNodeID: 6\n};\n\n/**\n * @enum {number}\n */\nconst resourceFormatIDs = {\n StandardMIDIFile: 0,\n StandardMIDIFileType1: 1,\n DLS1: 2,\n DLS2: 3,\n DLS22: 4,\n mobileDLS: 5\n};\n\n/**\n * @enum {number}\n */\nconst formatTypeIDs = {\n standard: 0,\n MMA: 1,\n registered: 2,\n nonRegistered: 3\n};\n\n\n/**\n * @enum {number}\n */\nconst unpackerIDs = {\n none: 0,\n MMAUnpacker: 1,\n registered: 2,\n nonRegistered: 3\n};\n\nclass XMFNode\n{\n /**\n * @type {number}\n */\n length;\n /**\n * 0 means it's a file node\n * @type {number}\n */\n itemCount;\n /**\n * @type {number}\n */\n metadataLength;\n \n /**\n * @type {Object<string, any>}\n */\n metadata = {};\n \n /**\n * @type {IndexedByteArray}\n */\n nodeData;\n \n /**\n * @type {XMFNode[]}\n */\n innerNodes = [];\n \n packedContent = false;\n \n nodeUnpackers = [];\n \n \n /**\n * @type {\"StandardMIDIFile\"|\n * \"StandardMIDIFileType1\"|\n * \"DLS1\"|\n * \"DLS2\"|\n * \"DLS22\"|\n * \"mobileDLS\"|\n * \"unknown\"|\"folder\"}\n */\n resourceFormat = \"unknown\";\n \n /**\n * @param binaryData {IndexedByteArray}\n */\n constructor(binaryData)\n {\n let 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 /**\n * @type {metadataTypes|string|number}\n */\n let fieldSpecifier;\n let key;\n while (metadataChunk.currentIndex < metadataChunk.length)\n {\n const firstSpecifierByte = metadataChunk[metadataChunk.currentIndex];\n if (firstSpecifierByte === 0)\n {\n metadataChunk.currentIndex++;\n fieldSpecifier = readVariableLengthQuantity(metadataChunk);\n if (Object.values(metadataTypes).indexOf(fieldSpecifier) === -1)\n {\n SpessaSynthWarn(`Unknown field specifier: ${fieldSpecifier}`);\n key = `unknown_${fieldSpecifier}`;\n }\n else\n {\n key = Object.keys(metadataTypes).find(k => metadataTypes[k] === fieldSpecifier);\n }\n }\n else\n {\n // this is the length of string\n const stringLength = readVariableLengthQuantity(metadataChunk);\n fieldSpecifier = readBytesAsString(metadataChunk, stringLength);\n key = fieldSpecifier;\n }\n \n const numberOfVersions = readVariableLengthQuantity(metadataChunk);\n if (numberOfVersions === 0)\n {\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 {\n this.metadata[key] = readBytesAsString(contentsChunk, dataLength - 1);\n }\n else\n {\n this.metadata[key] = contentsChunk.slice(contentsChunk.currentIndex);\n }\n }\n else\n {\n // throw new Error (\"International content is not supported.\");\n // Skip the number of versions\n SpessaSynthWarn(`International content: ${numberOfVersions}`);\n // Length in bytes\n // Skip the whole thing!\n metadataChunk.currentIndex += readVariableLengthQuantity(metadataChunk);\n }\n }\n \n const unpackersStart = headerData.currentIndex;\n const unpackersLength = readVariableLengthQuantity(headerData);\n const unpackersData = headerData.slice(headerData.currentIndex, unpackersStart + unpackersLength);\n headerData.currentIndex = unpackersStart + unpackersLength;\n if (unpackersLength > 0)\n {\n this.packedContent = true;\n while (unpackersData.currentIndex < unpackersLength)\n {\n const unpacker = {};\n unpacker.id = readVariableLengthQuantity(unpackersData);\n switch (unpacker.id)\n {\n case unpackerIDs.nonRegistered:\n case unpackerIDs.registered:\n SpessaSynthGroupEnd();\n throw new Error(`Unsupported unpacker ID: ${unpacker.id}`);\n \n default:\n SpessaSynthGroupEnd();\n throw new Error(`Unknown unpacker ID: ${unpacker.id}`);\n \n case unpackerIDs.none:\n unpacker.standardID = readVariableLengthQuantity(unpackersData);\n break;\n \n case unpackerIDs.MMAUnpacker:\n let manufacturerID = unpackersData[unpackersData.currentIndex++];\n // one or three byte form, depending on if the first byte is zero\n if (manufacturerID === 0)\n {\n manufacturerID <<= 8;\n manufacturerID |= unpackersData[unpackersData.currentIndex++];\n manufacturerID <<= 8;\n manufacturerID |= unpackersData[unpackersData.currentIndex++];\n }\n const manufacturerInternalID = readVariableLengthQuantity(unpackersData);\n unpacker.manufacturerID = manufacturerID;\n unpacker.manufacturerInternalID = manufacturerInternalID;\n break;\n }\n unpacker.decodedSize = readVariableLengthQuantity(unpackersData);\n this.nodeUnpackers.push(unpacker);\n }\n }\n binaryData.currentIndex = nodeStartIndex + headerLength;\n /**\n * @type {referenceTypeIds|number}\n */\n this.referenceTypeID = readVariableLengthQuantity(binaryData);\n this.nodeData = binaryData.slice(binaryData.currentIndex, nodeStartIndex + this.length);\n binaryData.currentIndex = nodeStartIndex + this.length;\n switch (this.referenceTypeID)\n {\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(`Unsupported reference type: ${this.referenceTypeID}`);\n \n default:\n SpessaSynthGroupEnd();\n throw new Error(`Unknown reference type: ${this.referenceTypeID}`);\n }\n \n // read the data\n if (this.isFile)\n {\n if (this.packedContent)\n {\n const compressed = this.nodeData.slice(2, this.nodeData.length);\n SpessaSynthInfo(\n `%cPacked content. Attemting to deflate. Target size: %c${this.nodeUnpackers[0].decodedSize}`,\n consoleColors.warn,\n consoleColors.value\n );\n try\n {\n this.nodeData = new IndexedByteArray(inflateSync(compressed).buffer);\n }\n catch (e)\n {\n SpessaSynthGroupEnd();\n throw new Error(`Error unpacking XMF file contents: ${e.message}.`);\n }\n }\n /**\n * interpret the content\n * @type {number[]}\n */\n const resourceFormat = this.metadata[\"resourceFormat\"];\n if (resourceFormat === undefined)\n {\n SpessaSynthWarn(\"No resource format for this file node!\");\n }\n else\n {\n const formatTypeID = resourceFormat[0];\n if (formatTypeID !== formatTypeIDs.standard)\n {\n SpessaSynthWarn(`Non-standard formatTypeID: ${resourceFormat}`);\n this.resourceFormat = resourceFormat.toString();\n }\n const resourceFormatID = resourceFormat[1];\n if (Object.values(resourceFormatIDs).indexOf(resourceFormatID) === -1)\n {\n SpessaSynthWarn(`Unrecognized resource format: ${resourceFormatID}`);\n }\n else\n {\n this.resourceFormat = Object.keys(resourceFormatIDs)\n .find(k => resourceFormatIDs[k] === resourceFormatID);\n }\n }\n }\n else\n {\n // folder node\n this.resourceFormat = \"folder\";\n while (this.nodeData.currentIndex < this.nodeData.length)\n {\n const nodeStartIndex = this.nodeData.currentIndex;\n const nodeLength = readVariableLengthQuantity(this.nodeData);\n const nodeData = this.nodeData.slice(nodeStartIndex, nodeStartIndex + nodeLength);\n this.nodeData.currentIndex = nodeStartIndex + nodeLength;\n this.innerNodes.push(new XMFNode(nodeData));\n }\n }\n }\n \n get isFile()\n {\n return this.itemCount === 0;\n }\n}\n\n/**\n * @param midi {MIDI}\n * @param binaryData {IndexedByteArray}\n * @returns {IndexedByteArray} the file byte array\n */\nexport function loadXMF(midi, binaryData)\n{\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 = readBytesAsString(binaryData, 4);\n if (sanityCheck !== \"XMF_\")\n {\n SpessaSynthGroupEnd();\n throw new SyntaxError(`Invalid XMF Header! Expected \"_XMF\", got \"${sanityCheck}\"`);\n }\n \n SpessaSynthGroup(\"%cParsing XMF file...\", consoleColors.info);\n const version = readBytesAsString(binaryData, 4);\n SpessaSynthInfo(\n `%cXMF version: %c${version}`,\n consoleColors.info, 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 {\n const fileTypeId = readBytesAsUintBigEndian(binaryData, 4);\n const fileTypeRevisionId = readBytesAsUintBigEndian(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 /**\n * @type {IndexedByteArray}\n */\n let midiArray;\n /**\n * find the stuff we care about\n * @param node {XMFNode}\n */\n const searchNode = node =>\n {\n const checkMeta = (xmf, rmid) =>\n {\n if (node.metadata[xmf] !== undefined && typeof node.metadata[xmf] === \"string\")\n {\n midi.RMIDInfo[rmid] = node.metadata[xmf];\n }\n };\n // meta\n checkMeta(\"nodeName\", RMIDINFOChunks.name);\n checkMeta(\"title\", RMIDINFOChunks.name);\n checkMeta(\"copyrightNotice\", RMIDINFOChunks.copyright);\n checkMeta(\"comment\", RMIDINFOChunks.comment);\n if (node.isFile)\n {\n switch (node.resourceFormat)\n {\n default:\n return;\n case \"DLS1\":\n case \"DLS2\":\n case \"DLS22\":\n case \"mobileDLS\":\n SpessaSynthInfo(\"%cFound embedded DLS!\", consoleColors.recognized);\n midi.embeddedSoundFont = node.nodeData.buffer;\n break;\n \n case \"StandardMIDIFile\":\n case \"StandardMIDIFileType1\":\n SpessaSynthInfo(\"%cFound embedded MIDI!\", consoleColors.recognized);\n midiArray = node.nodeData;\n break;\n }\n }\n else\n {\n for (const n of node.innerNodes)\n {\n searchNode(n);\n }\n }\n };\n searchNode(rootNode);\n SpessaSynthGroupEnd();\n return midiArray;\n}", "import { dataBytesAmount, getChannel, MIDIMessage } from \"./midi_message.js\";\nimport { IndexedByteArray } from \"../utils/indexed_array.js\";\nimport { consoleColors } from \"../utils/other.js\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo, SpessaSynthWarn } from \"../utils/loggin.js\";\nimport { readRIFFChunk } from \"../soundfont/basic_soundfont/riff_chunk.js\";\nimport { readVariableLengthQuantity } from \"../utils/byte_functions/variable_length_quantity.js\";\nimport { readBytesAsUintBigEndian } from \"../utils/byte_functions/big_endian.js\";\nimport { readBytesAsString } from \"../utils/byte_functions/string.js\";\nimport { readLittleEndian } from \"../utils/byte_functions/little_endian.js\";\nimport { RMIDINFOChunks } from \"./midi_tools/rmidi_writer.js\";\nimport { BasicMIDI } from \"./basic_midi.js\";\nimport { loadXMF } from \"./xmf_loader.js\";\n\n/**\n * midi_loader.js\n * purpose:\n * parses a midi file for the seqyencer,\n * including things like marker or CC 2/4 loop detection, copyright detection, etc.\n */\n\n/**\n * The MIDI class is a MIDI file parser that reads a MIDI file and extracts all the necessary information from it.\n * Supported formats are .mid and .rmi files.\n */\nclass MIDI extends BasicMIDI\n{\n /**\n * Parses a given midi file\n * @param arrayBuffer {ArrayBuffer}\n * @param fileName {string} optional, replaces the decoded title if empty\n */\n constructor(arrayBuffer, fileName = \"\")\n {\n super();\n SpessaSynthGroupCollapsed(`%cParsing MIDI File...`, consoleColors.info);\n this.fileName = fileName;\n const binaryData = new IndexedByteArray(arrayBuffer);\n let fileByteArray;\n \n // check for rmid\n const initialString = readBytesAsString(binaryData, 4);\n binaryData.currentIndex -= 4;\n if (initialString === \"RIFF\")\n {\n // possibly an RMID file (https://github.com/spessasus/sf2-rmidi-specification#readme)\n // skip size\n binaryData.currentIndex += 8;\n const rmid = readBytesAsString(binaryData, 4, undefined, false);\n if (rmid !== \"RMID\")\n {\n SpessaSynthGroupEnd();\n throw new SyntaxError(`Invalid RMIDI Header! Expected \"RMID\", got \"${rmid}\"`);\n }\n const riff = readRIFFChunk(binaryData);\n if (riff.header !== \"data\")\n {\n SpessaSynthGroupEnd();\n throw new SyntaxError(`Invalid RMIDI Chunk header! Expected \"data\", got \"${rmid}\"`);\n }\n // this is a rmid, load the midi into an array for parsing\n fileByteArray = riff.chunkData;\n \n // keep loading chunks until we get the \"SFBK\" header\n while (binaryData.currentIndex <= binaryData.length)\n {\n const startIndex = binaryData.currentIndex;\n const currentChunk = readRIFFChunk(binaryData, true);\n if (currentChunk.header === \"RIFF\")\n {\n const type = readBytesAsString(currentChunk.chunkData, 4).toLowerCase();\n if (type === \"sfbk\" || type === \"sfpk\" || type === \"dls \")\n {\n SpessaSynthInfo(\"%cFound embedded soundfont!\", consoleColors.recognized);\n this.embeddedSoundFont = binaryData.slice(startIndex, startIndex + currentChunk.size).buffer;\n }\n else\n {\n SpessaSynthWarn(`Unknown RIFF chunk: \"${type}\"`);\n }\n if (type === \"dls \")\n {\n // Assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.\n this.isDLSRMIDI = true;\n }\n }\n else if (currentChunk.header === \"LIST\")\n {\n const type = readBytesAsString(currentChunk.chunkData, 4);\n if (type === \"INFO\")\n {\n SpessaSynthInfo(\"%cFound RMIDI INFO chunk!\", consoleColors.recognized);\n this.RMIDInfo = {};\n while (currentChunk.chunkData.currentIndex <= currentChunk.size)\n {\n const infoChunk = readRIFFChunk(currentChunk.chunkData, true);\n this.RMIDInfo[infoChunk.header] = infoChunk.chunkData;\n }\n if (this.RMIDInfo[\"ICOP\"])\n {\n // special case, overwrites the copyright components array\n this.copyright = readBytesAsString(\n this.RMIDInfo[\"ICOP\"],\n this.RMIDInfo[\"ICOP\"].length,\n undefined,\n false\n ).replaceAll(\"\\n\", \" \");\n }\n if (this.RMIDInfo[\"INAM\"])\n {\n this.rawMidiName = this.RMIDInfo[RMIDINFOChunks.name];\n // noinspection JSCheckFunctionSignatures\n this.midiName = readBytesAsString(\n this.rawMidiName,\n this.rawMidiName.length,\n undefined,\n false\n ).replaceAll(\"\\n\", \" \");\n }\n // these can be used interchangeably\n if (this.RMIDInfo[\"IALB\"] && !this.RMIDInfo[\"IPRD\"])\n {\n this.RMIDInfo[\"IPRD\"] = this.RMIDInfo[\"IALB\"];\n }\n if (this.RMIDInfo[\"IPRD\"] && !this.RMIDInfo[\"IALB\"])\n {\n this.RMIDInfo[\"IALB\"] = this.RMIDInfo[\"IPRD\"];\n }\n this.bankOffset = 1; // defaults to 1\n if (this.RMIDInfo[RMIDINFOChunks.bankOffset])\n {\n this.bankOffset = readLittleEndian(this.RMIDInfo[RMIDINFOChunks.bankOffset], 2);\n }\n }\n }\n }\n \n if (this.isDLSRMIDI)\n {\n // Assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.\n this.bankOffset = 0;\n }\n \n // if no embedded bank, assume 0\n if (this.embeddedSoundFont === undefined)\n {\n this.bankOffset = 0;\n }\n }\n else if (initialString === \"XMF_\")\n {\n // XMF file\n fileByteArray = loadXMF(this, binaryData);\n }\n else\n {\n fileByteArray = binaryData;\n }\n const headerChunk = this._readMIDIChunk(fileByteArray);\n if (headerChunk.type !== \"MThd\")\n {\n SpessaSynthGroupEnd();\n throw new SyntaxError(`Invalid MIDI Header! Expected \"MThd\", got \"${headerChunk.type}\"`);\n }\n \n if (headerChunk.size !== 6)\n {\n SpessaSynthGroupEnd();\n throw new RangeError(`Invalid MIDI header chunk size! Expected 6, got ${headerChunk.size}`);\n }\n \n // format\n this.format = readBytesAsUintBigEndian(headerChunk.data, 2);\n // tracks count\n this.tracksAmount = readBytesAsUintBigEndian(headerChunk.data, 2);\n // time division\n this.timeDivision = readBytesAsUintBigEndian(headerChunk.data, 2);\n // read all the tracks\n for (let i = 0; i < this.tracksAmount; i++)\n {\n /**\n * @type {MIDIMessage[]}\n */\n const track = [];\n const trackChunk = this._readMIDIChunk(fileByteArray);\n \n if (trackChunk.type !== \"MTrk\")\n {\n SpessaSynthGroupEnd();\n throw new SyntaxError(`Invalid track header! Expected \"MTrk\" got \"${trackChunk.type}\"`);\n }\n \n \n /**\n * MIDI running byte\n * @type {number}\n */\n let runningByte = undefined;\n \n let totalTicks = 0;\n // format 2 plays sequentially\n if (this.format === 2 && i > 0)\n {\n totalTicks += this.tracks[i - 1][this.tracks[i - 1].length - 1].ticks;\n }\n // loop until we reach the end of track\n while (trackChunk.data.currentIndex < trackChunk.size)\n {\n totalTicks += readVariableLengthQuantity(trackChunk.data);\n \n // check if the status byte is valid (IE. larger than 127)\n const statusByteCheck = trackChunk.data[trackChunk.data.currentIndex];\n \n let statusByte;\n // if we have a running byte and the status byte isn't valid\n if (runningByte !== undefined && statusByteCheck < 0x80)\n {\n statusByte = runningByte;\n }\n else\n { // noinspection PointlessBooleanExpressionJS\n if (runningByte === undefined && statusByteCheck < 0x80)\n {\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(`Unexpected byte with no running byte. (${statusByteCheck})`);\n }\n else\n {\n // if the status byte is valid, use that\n statusByte = trackChunk.data[trackChunk.data.currentIndex++];\n }\n }\n const statusByteChannel = getChannel(statusByte);\n \n let eventDataLength;\n \n // determine the message's length;\n switch (statusByteChannel)\n {\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[trackChunk.data.currentIndex++];\n eventDataLength = readVariableLengthQuantity(trackChunk.data);\n break;\n \n case -3:\n // sysex\n eventDataLength = readVariableLengthQuantity(trackChunk.data);\n break;\n \n default:\n // voice message\n // gets the midi message length\n eventDataLength = dataBytesAmount[statusByte >> 4];\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(trackChunk.data.slice(\n trackChunk.data.currentIndex,\n trackChunk.data.currentIndex + eventDataLength\n ), 0);\n const event = new MIDIMessage(totalTicks, statusByte, eventData);\n track.push(event);\n // advance the track chunk\n trackChunk.data.currentIndex += eventDataLength;\n }\n this.tracks.push(track);\n \n SpessaSynthInfo(\n `%cParsed %c${this.tracks.length}%c / %c${this.tracksAmount}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n }\n \n SpessaSynthInfo(\n `%cAll tracks parsed correctly!`,\n consoleColors.recognized\n );\n // parse the events\n this._parseInternal();\n SpessaSynthGroupEnd();\n SpessaSynthInfo(\n `%cMIDI file parsed. Total tick time: %c${this.lastVoiceEventTick}%c, total seconds time: %c${this.duration}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n }\n \n /**\n * @param fileByteArray {IndexedByteArray}\n * @returns {{type: string, size: number, data: IndexedByteArray}}\n * @private\n */\n _readMIDIChunk(fileByteArray)\n {\n const chunk = {};\n // type\n chunk.type = readBytesAsString(fileByteArray, 4);\n // size\n chunk.size = readBytesAsUintBigEndian(fileByteArray, 4);\n // data\n chunk.data = new IndexedByteArray(chunk.size);\n const dataSlice = fileByteArray.slice(fileByteArray.currentIndex, fileByteArray.currentIndex + chunk.size);\n chunk.data.set(dataSlice, 0);\n fileByteArray.currentIndex += chunk.size;\n return chunk;\n }\n}\n\nexport { MIDI };", "import { SpessaSynthProcessor } from \"./src/synthetizer/audio_engine/main_processor.js\";\nimport { SpessaSynthSequencer } from \"./src/sequencer/sequencer_engine.js\";\nimport {\n ALL_CHANNELS_OR_DIFFERENT_ACTION,\n DEFAULT_PERCUSSION,\n DEFAULT_SYNTH_MODE,\n MIDI_CHANNEL_COUNT,\n VOICE_CAP\n} from \"./src/synthetizer/synth_constants.js\";\nimport {\n channelConfiguration,\n NON_CC_INDEX_OFFSET\n} from \"./src/synthetizer/audio_engine/engine_components/controller_tables.js\";\nimport { KeyModifier } from \"./src/synthetizer/audio_engine/engine_components/key_modifier_manager.js\";\nimport {\n masterParameterType\n} from \"./src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js\";\nimport { SynthesizerSnapshot } from \"./src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js\";\nimport { ChannelSnapshot } from \"./src/synthetizer/audio_engine/snapshot/channel_snapshot.js\";\n\nimport { BasicSoundBank } from \"./src/soundfont/basic_soundfont/basic_soundfont.js\";\nimport { BasicSample } from \"./src/soundfont/basic_soundfont/basic_sample.js\";\nimport { BasicInstrumentZone, BasicPresetZone } from \"./src/soundfont/basic_soundfont/basic_zones.js\";\nimport { BasicInstrument } from \"./src/soundfont/basic_soundfont/basic_instrument.js\";\nimport { BasicPreset } from \"./src/soundfont/basic_soundfont/basic_preset.js\";\nimport { Generator } from \"./src/soundfont/basic_soundfont/generator.js\";\nimport { Modulator, modulatorSources } from \"./src/soundfont/basic_soundfont/modulator.js\";\nimport { loadSoundFont } from \"./src/soundfont/load_soundfont.js\";\n\nimport { MIDI } from \"./src/midi/midi_loader.js\";\nimport { BasicMIDI } from \"./src/midi/basic_midi.js\";\nimport { MIDISequenceData } from \"./src/midi/midi_sequence.js\";\nimport { MIDIBuilder } from \"./src/midi/midi_builder.js\";\nimport { messageTypes, midiControllers, MIDIMessage } from \"./src/midi/midi_message.js\";\nimport { interpolationTypes, synthDisplayTypes } from \"./src/synthetizer/audio_engine/engine_components/enums.js\";\nimport { RMIDINFOChunks } from \"./src/midi/midi_tools/rmidi_writer.js\";\nimport { IndexedByteArray } from \"./src/utils/indexed_array.js\";\nimport { audioToWav } from \"./src/utils/buffer_to_wav.js\";\nimport {\n SpessaSynthGroupCollapsed,\n SpessaSynthGroupEnd,\n SpessaSynthInfo,\n SpessaSynthLogging,\n SpessaSynthWarn\n} from \"./src/utils/loggin.js\";\nimport { readBytesAsUintBigEndian } from \"./src/utils/byte_functions/big_endian.js\";\nimport { readLittleEndian } from \"./src/utils/byte_functions/little_endian.js\";\nimport { readBytesAsString } from \"./src/utils/byte_functions/string.js\";\nimport { readVariableLengthQuantity } from \"./src/utils/byte_functions/variable_length_quantity.js\";\nimport { consoleColors } from \"./src/utils/other.js\";\nimport { inflateSync } from \"./src/externals/fflate/fflate.min.js\";\n\n// you shouldn't use these...\nconst SpessaSynthCoreUtils = {\n consoleColors,\n SpessaSynthInfo,\n SpessaSynthWarn,\n SpessaSynthGroupCollapsed,\n SpessaSynthGroupEnd,\n readBytesAsUintBigEndian,\n readLittleEndian,\n readBytesAsString,\n readVariableLengthQuantity,\n inflateSync\n};\n\nexport {\n // synth and seq\n SpessaSynthSequencer,\n SpessaSynthProcessor,\n SynthesizerSnapshot,\n ChannelSnapshot,\n KeyModifier,\n masterParameterType,\n channelConfiguration,\n interpolationTypes,\n synthDisplayTypes,\n DEFAULT_PERCUSSION,\n VOICE_CAP,\n ALL_CHANNELS_OR_DIFFERENT_ACTION,\n NON_CC_INDEX_OFFSET,\n DEFAULT_SYNTH_MODE,\n MIDI_CHANNEL_COUNT,\n \n // sound banks\n loadSoundFont,\n BasicSoundBank,\n BasicSample,\n BasicInstrumentZone,\n BasicInstrument,\n BasicPreset,\n BasicPresetZone,\n Generator,\n Modulator,\n modulatorSources,\n \n // MIDI\n MIDI,\n MIDISequenceData,\n BasicMIDI,\n MIDIBuilder,\n MIDIMessage,\n RMIDINFOChunks,\n \n // utils\n IndexedByteArray,\n audioToWav,\n SpessaSynthLogging,\n midiControllers,\n messageTypes,\n SpessaSynthCoreUtils\n};", "/**\n * other.js\n * purpose: contains some useful functions that don't belong in any specific category\n */\n\nimport { SpessaSynthCoreUtils } from \"spessasynth_core\";\n\nconst consoleColors = SpessaSynthCoreUtils.consoleColors;\n\nexport { consoleColors };\n\n", "import { SynthesizerSnapshot } from \"spessasynth_core\";\n\n/**\n * @enum {number}\n * // NOTE: Every message needs a channel number (if not relevant or all, set to -1)\n * @property {number} midiMessage - 0 -> [messageData<Uint8Array>, channelOffset<number>, force<boolean>, options<SynthMethodOptions>]\n * @property {number} ccReset - 7 -> (no data) note: if channel is -1 then reset all channels\n * @property {number} setChannelVibrato - 8 -> {frequencyHz: number, depthCents: number, delaySeconds: number} note: if channel is -1 then stop all channels note 2: if rate is -1, it means locking\n * @property {number} soundFontManager - 9 -> [messageType<WorkletSoundfontManagerMessageType> messageData<any>] note: refer to sfman_message.js\n * @property {number} stopAll - 10 -> force<number> (0 false, 1 true) note: if channel is -1 then stop all channels\n * @property {number} killNotes - 11 -> amount<number>\n * @property {number} muteChannel - 12 -> isMuted<boolean>\n * @property {number} addNewChannel - 13 -> (no data)\n * @property {number} customCcChange - 14 -> [ccNumber<number>, ccValue<number>]\n * @property {number} debugMessage - 15 -> (no data)\n * @property {number} setMasterParameter - 17 -> [parameter<masterParameterType>, value<number>]\n * @property {number} setDrums - 18 -> isDrums<boolean>\n * @property {number} transpose - 19 -> [semitones<number>, force<boolean>] note: if channel is -1 then transpose all channels\n * @property {number} highPerformanceMode - 20 -> isOn<boolean>\n * @property {number} lockController - 21 -> [controllerNumber<number>, isLocked<boolean>]\n * @property {number} sequencerSpecific - 22 -> [messageType<SpessaSynthSequencerMessageType> messageData<any>] note: refer to sequencer_message.js\n * @property {number} requestSynthesizerSnapshot - 23 -> (no data)\n * @property {number} setLogLevel - 24 -> [enableInfo<boolean>, enableWarning<boolean>, enableGroup<boolean>, enableTable<boolean>]\n * @property {number} keyModifier - 25 -> [messageType<workletKeyModifierMessageType> messageData<any>]\n * @property {number} setEffectsGain - 26 -> [reverbGain<number>, chorusGain<number>]\n * @property {number} destroyWorklet - 27 -> (no data)\n */\nexport const workletMessageType = {\n midiMessage: 0,\n // free 6 slots here, use when needed instead of adding new ones\n ccReset: 7,\n setChannelVibrato: 8,\n soundFontManager: 9,\n stopAll: 10,\n killNotes: 11,\n muteChannel: 12,\n addNewChannel: 13,\n customCcChange: 14,\n debugMessage: 15,\n // free slot here\n setMasterParameter: 17,\n setDrums: 18,\n transpose: 19,\n highPerformanceMode: 20,\n lockController: 21,\n sequencerSpecific: 22,\n requestSynthesizerSnapshot: 23,\n setLogLevel: 24,\n keyModifierManager: 25,\n setEffectsGain: 26,\n destroyWorklet: 27\n};\n\n\n/**\n * @typedef {{\n * channelNumber: number\n * messageType: (workletMessageType|number),\n * messageData: (\n * boolean|\n * (number|Uint8Array|object)[]\n * |undefined\n * |boolean[]\n * |boolean\n * |Voice[]\n * |number\n * |{rate: number, depth: number, delay: number}\n * |ArrayBuffer\n * |{messageType: SpessaSynthSequencerMessageType, messageData: any}\n * |{messageType: workletKeyModifierMessageType, messageData: any}\n * )\n * }} WorkletMessage\n */\n\n/**\n * @typedef {Object} ChannelProperty\n * @property {number} voicesAmount - the channel's current voice amount\n * @property {number} pitchBend - the channel's current pitch bend from -8192 do 8192\n * @property {number} pitchBendRangeSemitones - the pitch bend's range, in semitones\n * @property {boolean} isMuted - indicates whether the channel is muted\n * @property {boolean} isDrum - indicates whether the channel is a drum channel\n * @property {number} transposition - the channel's transposition, in semitones\n * @property {number} bank - the bank number of the current preset\n * @property {number} program - the MIDI program number of the current preset\n */\n\n/**\n * @typedef {Object} WorkletReturnMessage\n * @property {returnMessageType} messageType - the message's type\n * @property {{\n * eventName: string,\n * eventData: any\n * }|ChannelProperty\n * |{presetName: string, bank: number, program: number}[]\n * |string\n * |{messageType: SpessaSynthSequencerReturnMessageType, messageData: any}\n * |SynthesizerSnapshot\n * |[WorkletSoundfontManagerMessageType, any]} messageData - the message's data\n *\n * 0 - channel property change -> [channel<number>, property<ChannelProperty>] see message_sending.js line 29\n * 1 - event call -> {eventName<string>, eventData:<the event's data>}\n * 2 - master parameter change -> [parameter<masterParameterType>, value<string|number>]\n * 3 - sequencer specific -> [messageType<SpessaSynthSequencerReturnMessageType> messageData<any>] note: refer to sequencer_message.js\n * 4 - synthesizer snapshot -> snapshot<SynthesizerSnapshot> note: refer to synthesizer_snapshot.js\n * 5 - isFullyInitialized -> (no data)\n * 6 - soundfontError -> errorMessage<string>\n */\n\n/**\n * @enum {number}\n */\nexport const returnMessageType = {\n channelPropertyChange: 0,\n eventCall: 1,\n masterParameterChange: 2,\n sequencerSpecific: 3,\n synthesizerSnapshot: 4,\n isFullyInitialized: 5,\n soundfontError: 6\n};", "import { BasicMIDI, SynthesizerSnapshot } from \"spessasynth_core\";\n\n/**\n * The absolute path (from the spessasynth_lib folder) to the worklet module\n * @type {string}\n */\nexport const WORKLET_URL_ABSOLUTE = \"synthetizer/worklet_processor.min.js\";\n/**\n * @typedef {Object} StartRenderingDataConfig\n * @property {BasicMIDI} parsedMIDI - the MIDI to render\n * @property {SynthesizerSnapshot?} snapshot - the snapshot to apply\n * @property {boolean?} oneOutput - if synth should use one output with 32 channels (2 audio channels for each midi channel).\n * this disabled chorus and reverb.\n * @property {number?} loopCount - the times to loop the song\n * @property {SequencerOptions?} sequencerOptions - the options to pass to the sequencer\n */\n\nexport const WORKLET_PROCESSOR_NAME = \"spessasynth-worklet-processor\";", "import { workletMessageType } from \"./worklet_message.js\";\nimport { KeyModifier } from \"spessasynth_core\";\n\n/**\n * @enum {number}\n */\nexport const workletKeyModifierMessageType = {\n addMapping: 0, // [channel<number>, midiNote<number>, mapping<KeyModifier>]\n deleteMapping: 1, // [channel<number>, midiNote<number>]\n clearMappings: 2 // <no data>\n};\n\nexport class WorkletKeyModifierManagerWrapper\n{\n /**\n * @param synth {Synthetizer}\n */\n constructor(synth)\n {\n this.synth = synth;\n /**\n * The velocity override mappings for MIDI keys\n * @type {KeyModifier[][]}\n * @private\n */\n this._keyModifiers = [];\n }\n \n /**\n * @private\n * @param type {workletKeyModifierMessageType}\n * @param data {any}\n */\n _sendToWorklet(type, data)\n {\n this.synth.post({\n messageType: workletMessageType.keyModifierManager,\n messageData: [\n type,\n data\n ]\n });\n }\n \n /**\n * Modifies a single key\n * @param channel {number} the channel affected. Usually 0-15\n * @param midiNote {number} the MIDI note to change. 0-127\n * @param options {{\n * velocity: number|undefined,\n * patch: {\n * bank: number,\n * program: number\n * }|undefined,\n * gain: number|undefined\n * }} the key's modifiers\n */\n addModifier(channel, midiNote, options)\n {\n const velocity = options?.velocity ?? -1;\n const program = options?.patch?.program ?? -1;\n const bank = options?.patch?.bank ?? -1;\n const gain = options?.gain ?? 1;\n const mod = new KeyModifier(velocity, bank, program, gain);\n if (this._keyModifiers[channel] === undefined)\n {\n this._keyModifiers[channel] = [];\n }\n this._keyModifiers[channel][midiNote] = mod;\n this._sendToWorklet(\n workletKeyModifierMessageType.addMapping,\n [channel, midiNote, mod]\n );\n }\n \n /**\n * Gets a key modifier\n * @param channel {number} the channel affected. Usually 0-15\n * @param midiNote {number} the MIDI note to change. 0-127\n * @returns {KeyModifier|undefined}\n */\n getModifier(channel, midiNote)\n {\n return this._keyModifiers?.[channel]?.[midiNote];\n }\n \n /**\n * Deletes a key modifier\n * @param channel {number} the channel affected. Usually 0-15\n * @param midiNote {number} the MIDI note to change. 0-127\n */\n deleteModifier(channel, midiNote)\n {\n this._sendToWorklet(\n workletKeyModifierMessageType.deleteMapping,\n [channel, midiNote]\n );\n if (this._keyModifiers[channel]?.[midiNote] === undefined)\n {\n return;\n }\n this._keyModifiers[channel][midiNote] = undefined;\n }\n \n /**\n * Clears ALL Modifiers\n */\n clearModifiers()\n {\n this._sendToWorklet(workletKeyModifierMessageType.clearMappings, undefined);\n this._keyModifiers = [];\n }\n}", "/**\n * @enum {number}\n */\nexport const WorkletSoundfontManagerMessageType = {\n reloadSoundFont: 0, // buffer<ArrayBuffer>\n addNewSoundFont: 2, // [buffer<ArrayBuffer>, id<string>, bankOffset<number>]\n deleteSoundFont: 3, // id<string>\n rearrangeSoundFonts: 4 // newOrder<string[]> // where string is the id\n};", "export const SongChangeType = {\n backwards: 0, // no additional data\n forwards: 1, // no additional data\n shuffleOn: 2, // no additional data\n shuffleOff: 3, // no additional data\n index: 4 // songIndex<number>\n};\n\n/**\n * @enum {number}\n * @property {number} loadNewSongList - 0 -> [...song<MIDI>]\n * @property {number} pause - 1 -> isFinished<boolean>\n * @property {number} stop - 2 -> (no data)\n * @property {number} play - 3 -> resetTime<boolean>\n * @property {number} setTime - 4 -> time<number>\n * @property {number} changeMIDIMessageSending - 5 -> sendMIDIMessages<boolean>\n * @property {number} setPlaybackRate - 6 -> playbackRate<number>\n * @property {number} setLoop - 7 -> [loop<boolean>, count<number>]\n * @property {number} changeSong - 8 -> [changeType<SongChangeType>, data<number>]\n * @property {number} getMIDI - 9 -> (no data)\n * @property {number} setSkipToFirstNote -10 -> skipToFirstNoteOn<boolean>\n * @property {number} setPreservePlaybackState -11 -> preservePlaybackState<boolean>\n */\nexport const SpessaSynthSequencerMessageType = {\n loadNewSongList: 0,\n pause: 1,\n stop: 2,\n play: 3,\n setTime: 4,\n changeMIDIMessageSending: 5,\n setPlaybackRate: 6,\n setLoop: 7,\n changeSong: 8,\n getMIDI: 9,\n setSkipToFirstNote: 10,\n setPreservePlaybackState: 11\n};\n\n/**\n *\n * @enum {number}\n */\nexport const SpessaSynthSequencerReturnMessageType = {\n midiEvent: 0, // [...midiEventBytes<number>]\n songChange: 1, // [songIndex<number>, isAutoPlayed<boolean>]\n timeChange: 2, // newTime<number>\n pause: 3, // no data\n getMIDI: 4, // midiData<MIDI>\n midiError: 5, // errorMSG<string>\n metaEvent: 6, // [event<MIDIMessage>, trackNum<number>]\n loopCountChange: 7, // newLoopCount<number>\n songListChange: 8 // songListData<MIDIData[]>\n};", "/**\n * Fills the object with default values\n * @param obj {Object}\n * @param defObj {Object}\n * @returns {Object}\n */\nexport function fillWithDefaults(obj, defObj)\n{\n if (obj === undefined)\n {\n obj = {};\n }\n for (const key in defObj)\n {\n if (defObj.hasOwnProperty(key) && !(key in obj))\n {\n obj[key] = defObj[key];\n }\n }\n return obj;\n}", "/**\n * @type {SequencerOptions}\n */\nexport const DEFAULT_SEQUENCER_OPTIONS = {\n skipToFirstNoteOn: true,\n autoPlay: true,\n preservePlaybackState: false\n};", "import { BasicMIDI, MIDISequenceData } from \"spessasynth_core\";\n\n/**\n * A simplified version of the MIDI, accessible at all times from the Sequencer.\n * Use getMIDI() to get the actual sequence.\n * This class contains all properties that MIDI does, except for tracks and the embedded soundfont.\n */\nexport class MIDIData extends MIDISequenceData\n{\n \n /**\n * A boolean indicating if the MIDI file contains an embedded soundfont.\n * If the embedded soundfont is undefined, this will be false.\n * @type {boolean}\n */\n isEmbedded = false;\n \n /**\n * Constructor that copies data from a BasicMIDI instance.\n * @param {BasicMIDI} midi - The BasicMIDI instance to copy data from.\n */\n constructor(midi)\n {\n super();\n this._copyFromSequence(midi);\n \n // Set isEmbedded based on the presence of an embeddedSoundFont\n this.isEmbedded = midi.embeddedSoundFont !== undefined;\n }\n}\n\n\n/**\n * Temporary MIDI data used when the MIDI is not loaded.\n * @type {MIDIData}\n */\nexport const DUMMY_MIDI_DATA = {\n duration: 99999,\n firstNoteOn: 0,\n loop: {\n start: 0,\n end: 123456\n },\n \n lastVoiceEventTick: 123456,\n lyrics: [],\n copyright: \"\",\n midiPorts: [],\n midiPortChannelOffsets: [],\n tracksAmount: 0,\n tempoChanges: [{ ticks: 0, tempo: 120 }],\n fileName: \"NOT_LOADED.mid\",\n midiName: \"Loading...\",\n rawMidiName: new Uint8Array([76, 111, 97, 100, 105, 110, 103, 46, 46, 46]), // \"Loading...\"\n usedChannelsOnTrack: [],\n timeDivision: 0,\n keyRange: { min: 0, max: 127 },\n isEmbedded: false,\n RMIDInfo: {},\n bankOffset: 0,\n midiNameUsesFileName: false,\n format: 0\n};", "import { consoleColors } from \"../utils/other.js\";\nimport {\n ALL_CHANNELS_OR_DIFFERENT_ACTION,\n BasicMIDI,\n masterParameterType,\n MIDI,\n MIDI_CHANNEL_COUNT,\n SpessaSynthCoreUtils as util,\n SpessaSynthLogging,\n SpessaSynthProcessor,\n SpessaSynthSequencer,\n SynthesizerSnapshot\n} from \"spessasynth_core\";\nimport { returnMessageType, workletMessageType } from \"./worklet_message.js\";\nimport { WORKLET_PROCESSOR_NAME } from \"./worklet_url.js\";\nimport { workletKeyModifierMessageType } from \"./key_modifier_manager.js\";\nimport { WorkletSoundfontManagerMessageType } from \"./sfman_message.js\";\nimport {\n SongChangeType,\n SpessaSynthSequencerMessageType,\n SpessaSynthSequencerReturnMessageType\n} from \"../sequencer/sequencer_message.js\";\nimport { fillWithDefaults } from \"../utils/fill_with_defaults.js\";\nimport { DEFAULT_SEQUENCER_OPTIONS } from \"../sequencer/default_sequencer_options.js\";\nimport { MIDIData } from \"../sequencer/midi_data.js\";\n\n\n// a worklet processor wrapper for the synthesizer core\nclass WorkletSpessaProcessor extends AudioWorkletProcessor\n{\n /**\n * If the worklet is alive\n * @type {boolean}\n */\n alive = true;\n \n /**\n * Instead of 18 stereo outputs, there's one with 32 channels (no effects)\n * @type {boolean}\n */\n oneOutputMode = false;\n \n /**\n * Creates a new worklet synthesis system. contains all channels\n * @param options {{\n * processorOptions: {\n * midiChannels: number,\n * soundfont: ArrayBuffer,\n * enableEventSystem: boolean,\n * startRenderingData: StartRenderingDataConfig\n * }}}\n */\n constructor(options)\n {\n super();\n const opts = options.processorOptions;\n \n \n // one output is indicated by setting midiChannels to 1\n this.oneOutputMode = opts.midiChannels === 1;\n \n // prepare synthesizer connections\n /**\n * @param t {returnMessageType}\n * @param d {any}\n */\n const postSyn = (t, d) =>\n {\n // noinspection JSCheckFunctionSignatures\n this.postMessageToMainThread({\n messageType: t,\n messageData: d\n });\n };\n \n // start rendering data\n const startRenderingData = opts?.startRenderingData;\n /**\n * The snapshot that synth was restored from\n * @type {SynthesizerSnapshot|undefined}\n * @private\n */\n const snapshot = startRenderingData?.snapshot;\n \n // noinspection JSUnresolvedReference\n /**\n * Initialize the synthesis engine\n * @type {SpessaSynthProcessor}\n */\n this.synthesizer = new SpessaSynthProcessor(\n opts.soundfont, // initial sound bank\n sampleRate, // AudioWorkletGlobalScope\n {\n eventCall: (t, d) =>\n {\n postSyn(returnMessageType.eventCall, {\n eventName: t,\n eventData: d\n });\n },\n ready: this.postReady.bind(this),\n channelPropertyChange: (p, n) => postSyn(returnMessageType.channelPropertyChange, [n, p]),\n masterParameterChange: (t, v) => postSyn(returnMessageType.masterParameterChange, [t, v])\n },\n !this.oneOutputMode, // one output mode disables effects\n opts?.enableEventSystem, // enable message port?\n currentTime, // AudioWorkletGlobalScope, sync with audioContext time\n MIDI_CHANNEL_COUNT, // midi channel count (16)\n snapshot\n );\n \n // initialize the sequencer engine\n this.sequencer = new SpessaSynthSequencer(this.synthesizer);\n \n const postSeq = (type, data) =>\n {\n this.postMessageToMainThread({\n messageType: returnMessageType.sequencerSpecific,\n messageData: {\n messageType: type,\n messageData: data\n }\n });\n };\n \n // receive messages from the main thread\n this.port.onmessage = e => this.handleMessage(e.data);\n \n // sequencer events\n this.sequencer.onMIDIMessage = m =>\n {\n postSeq(SpessaSynthSequencerReturnMessageType.midiEvent, m);\n };\n this.sequencer.onTimeChange = t =>\n {\n postSeq(SpessaSynthSequencerReturnMessageType.timeChange, t);\n };\n this.sequencer.onPlaybackStop = p =>\n {\n postSeq(SpessaSynthSequencerReturnMessageType.pause, p);\n };\n this.sequencer.onSongChange = (i, a) =>\n {\n postSeq(SpessaSynthSequencerReturnMessageType.songChange, [i, a]);\n };\n this.sequencer.onMetaEvent = (e, i) =>\n {\n postSeq(SpessaSynthSequencerReturnMessageType.metaEvent, [e, i]);\n };\n this.sequencer.onLoopCountChange = c =>\n {\n postSeq(SpessaSynthSequencerReturnMessageType.loopCountChange, c);\n };\n this.sequencer.onSongListChange = l =>\n {\n const midiDataList = l.map(s => new MIDIData(s));\n this.postMessageToMainThread({\n messageType: returnMessageType.sequencerSpecific,\n messageData: {\n messageType: SpessaSynthSequencerReturnMessageType.songListChange,\n messageData: midiDataList\n }\n });\n };\n \n // if sent, start rendering\n if (startRenderingData)\n {\n if (snapshot !== undefined)\n {\n this.synthesizer.applySynthesizerSnapshot(snapshot);\n }\n \n util.SpessaSynthInfo(\"%cRendering enabled! Starting render.\", consoleColors.info);\n if (startRenderingData.parsedMIDI)\n {\n if (startRenderingData?.loopCount !== undefined)\n {\n this.sequencer.loopCount = startRenderingData?.loopCount;\n this.sequencer.loop = true;\n }\n else\n {\n this.sequencer.loop = false;\n }\n // set voice cap to unlimited\n this.synthesizer.voiceCap = Infinity;\n this.synthesizer.processorInitialized.then(() =>\n {\n /**\n * set options\n * @type {SequencerOptions}\n */\n const seqOptions = fillWithDefaults(\n startRenderingData.sequencerOptions,\n DEFAULT_SEQUENCER_OPTIONS\n );\n this.sequencer.skipToFirstNoteOn = seqOptions.skipToFirstNoteOn;\n this.sequencer.preservePlaybackState = seqOptions.preservePlaybackState;\n // autoplay is ignored\n try\n {\n this.sequencer.loadNewSongList([startRenderingData.parsedMIDI]);\n }\n catch (e)\n {\n console.error(e);\n postSeq(SpessaSynthSequencerReturnMessageType.midiError, e);\n }\n });\n }\n }\n }\n \n postReady()\n {\n this.postMessageToMainThread({\n messageType: returnMessageType.isFullyInitialized,\n messageData: undefined\n });\n }\n \n /**\n * @param data {WorkletReturnMessage}\n */\n postMessageToMainThread(data)\n {\n this.port.postMessage(data);\n }\n \n /**\n * @this {WorkletSpessaProcessor}\n * @param message {WorkletMessage}\n */\n handleMessage(message)\n {\n const data = message.messageData;\n const channel = message.channelNumber;\n \n let channelObject;\n if (channel >= 0)\n {\n channelObject = this.synthesizer.midiAudioChannels[channel];\n if (channelObject === undefined)\n {\n util.SpessaSynthWarn(`Trying to access channel ${channel} which does not exist... ignoring!`);\n return;\n }\n }\n switch (message.messageType)\n {\n case workletMessageType.midiMessage:\n this.synthesizer.processMessage(...data);\n break;\n \n case workletMessageType.customCcChange:\n // custom controller change\n channelObject.setCustomController(data[0], data[1]);\n channelObject.updateChannelTuning();\n break;\n \n case workletMessageType.ccReset:\n if (channel === ALL_CHANNELS_OR_DIFFERENT_ACTION)\n {\n this.synthesizer.resetAllControllers();\n }\n else\n {\n channelObject.resetControllers();\n }\n break;\n \n case workletMessageType.setChannelVibrato:\n if (channel === ALL_CHANNELS_OR_DIFFERENT_ACTION)\n {\n for (let i = 0; i < this.synthesizer.midiAudioChannels.length; i++)\n {\n const chan = this.synthesizer.midiAudioChannels[i];\n if (data.rate === ALL_CHANNELS_OR_DIFFERENT_ACTION)\n {\n chan.disableAndLockGSNRPN();\n }\n else\n {\n chan.setVibrato(data.depth, data.rate, data.delay);\n }\n }\n }\n else if (data.rate === ALL_CHANNELS_OR_DIFFERENT_ACTION)\n {\n channelObject.disableAndLockGSNRPN();\n }\n else\n {\n channelObject.setVibrato(data.depth, data.rate, data.delay);\n }\n break;\n \n case workletMessageType.stopAll:\n if (channel === ALL_CHANNELS_OR_DIFFERENT_ACTION)\n {\n this.synthesizer.stopAllChannels(data === 1);\n }\n else\n {\n channelObject.stopAllNotes(data === 1);\n }\n break;\n \n case workletMessageType.killNotes:\n this.synthesizer.voiceKilling(data);\n break;\n \n case workletMessageType.muteChannel:\n channelObject.muteChannel(data);\n break;\n \n case workletMessageType.addNewChannel:\n this.synthesizer.createWorkletChannel(true);\n break;\n \n case workletMessageType.debugMessage:\n console.debug(this.synthesizer);\n break;\n \n case workletMessageType.setMasterParameter:\n /**\n * @type {masterParameterType}\n */\n const type = data[0];\n const value = data[1];\n this.synthesizer.setMasterParameter(type, value);\n break;\n \n case workletMessageType.setDrums:\n channelObject.setDrums(data);\n break;\n \n case workletMessageType.transpose:\n if (channel === ALL_CHANNELS_OR_DIFFERENT_ACTION)\n {\n this.synthesizer.transposeAllChannels(data[0], data[1]);\n }\n else\n {\n channelObject.transposeChannel(data[0], data[1]);\n }\n break;\n \n case workletMessageType.highPerformanceMode:\n this.synthesizer.highPerformanceMode = data;\n break;\n \n case workletMessageType.lockController:\n if (data[0] === ALL_CHANNELS_OR_DIFFERENT_ACTION)\n {\n channelObject.setPresetLock(data[1]);\n }\n else\n {\n channelObject.lockedControllers[data[0]] = data[1];\n }\n break;\n \n case workletMessageType.sequencerSpecific:\n const seq = this.sequencer;\n const messageData = data.messageData;\n const messageType = data.messageType;\n switch (messageType)\n {\n default:\n break;\n \n case SpessaSynthSequencerMessageType.loadNewSongList:\n try\n {\n /**\n * @type {(BasicMIDI|{binary: ArrayBuffer, altName: string})[]}\n */\n const sList = messageData[0];\n const songMap = sList.map(s =>\n {\n if (s.duration)\n {\n return s;\n }\n return new MIDI(s.binary, s.altName);\n });\n seq.loadNewSongList(songMap, messageData[1]);\n }\n catch (e)\n {\n console.error(e);\n this.postMessageToMainThread({\n messageType: returnMessageType.sequencerSpecific,\n messageData: {\n messageType: SpessaSynthSequencerReturnMessageType.midiError,\n messageData: e\n }\n });\n }\n break;\n \n case SpessaSynthSequencerMessageType.pause:\n seq.pause();\n break;\n \n case SpessaSynthSequencerMessageType.play:\n seq.play(messageData);\n break;\n \n case SpessaSynthSequencerMessageType.stop:\n seq.stop();\n break;\n \n case SpessaSynthSequencerMessageType.setTime:\n seq.currentTime = messageData;\n break;\n \n case SpessaSynthSequencerMessageType.changeMIDIMessageSending:\n seq.sendMIDIMessages = messageData;\n break;\n \n case SpessaSynthSequencerMessageType.setPlaybackRate:\n seq.playbackRate = messageData;\n break;\n \n case SpessaSynthSequencerMessageType.setLoop:\n const [loop, count] = messageData;\n seq.loop = loop;\n if (count === ALL_CHANNELS_OR_DIFFERENT_ACTION)\n {\n seq.loopCount = Infinity;\n }\n else\n {\n seq.loopCount = count;\n }\n break;\n \n case SpessaSynthSequencerMessageType.changeSong:\n switch (messageData[0])\n {\n case SongChangeType.forwards:\n seq.nextSong();\n break;\n \n case SongChangeType.backwards:\n seq.previousSong();\n break;\n \n case SongChangeType.shuffleOff:\n seq.shuffleMode = false;\n seq.songIndex = seq.shuffledSongIndexes[seq.songIndex];\n break;\n \n case SongChangeType.shuffleOn:\n seq.shuffleMode = true;\n seq.shuffleSongIndexes();\n seq.songIndex = 0;\n seq.loadCurrentSong();\n break;\n \n case SongChangeType.index:\n seq.songIndex = messageData[1];\n seq.loadCurrentSong();\n break;\n }\n break;\n \n case SpessaSynthSequencerMessageType.getMIDI:\n this.postMessageToMainThread({\n messageType: returnMessageType.sequencerSpecific,\n messageData: {\n messageType: SpessaSynthSequencerReturnMessageType.getMIDI,\n messageData: seq.midiData\n }\n });\n break;\n \n case SpessaSynthSequencerMessageType.setSkipToFirstNote:\n seq.skipToFirstNoteOn = messageData;\n break;\n \n case SpessaSynthSequencerMessageType.setPreservePlaybackState:\n seq.preservePlaybackState = messageData;\n }\n break;\n \n case workletMessageType.soundFontManager:\n try\n {\n const sfManager = this.synthesizer.soundfontManager;\n const type = data[0];\n const messageData = data[1];\n switch (type)\n {\n case WorkletSoundfontManagerMessageType.addNewSoundFont:\n sfManager.addNewSoundFont(messageData[0], messageData[1], messageData[2]);\n this.postMessageToMainThread({\n messageType: returnMessageType.isFullyInitialized,\n messageData: undefined\n });\n break;\n \n case WorkletSoundfontManagerMessageType.reloadSoundFont:\n sfManager.reloadManager(messageData);\n this.postMessageToMainThread({\n messageType: returnMessageType.isFullyInitialized,\n messageData: undefined\n });\n break;\n \n case WorkletSoundfontManagerMessageType.deleteSoundFont:\n sfManager.deleteSoundFont(messageData);\n break;\n \n case WorkletSoundfontManagerMessageType.rearrangeSoundFonts:\n sfManager.rearrangeSoundFonts(messageData);\n }\n }\n catch (e)\n {\n this.postMessageToMainThread({\n messageType: returnMessageType.soundfontError,\n messageData: e\n });\n }\n this.synthesizer.clearSoundFont(true, false);\n break;\n \n case workletMessageType.keyModifierManager:\n /**\n * @type {workletKeyModifierMessageType}\n */\n const keyMessageType = data[0];\n const man = this.synthesizer.keyModifierManager;\n const keyMessageData = data[1];\n switch (keyMessageType)\n {\n default:\n return;\n \n case workletKeyModifierMessageType.addMapping:\n man.addMapping(...keyMessageData);\n break;\n \n case workletKeyModifierMessageType.clearMappings:\n man.clearMappings();\n break;\n \n case workletKeyModifierMessageType.deleteMapping:\n man.deleteMapping(...keyMessageData);\n }\n break;\n \n case workletMessageType.requestSynthesizerSnapshot:\n const snapshot = SynthesizerSnapshot.createSynthesizerSnapshot(this.synthesizer);\n this.postMessageToMainThread({\n messageType: returnMessageType.synthesizerSnapshot,\n messageData: snapshot\n });\n break;\n \n case workletMessageType.setLogLevel:\n SpessaSynthLogging(data[0], data[1], data[2], data[3]);\n break;\n \n case workletMessageType.setEffectsGain:\n this.synthesizer.reverbGain = data[0];\n this.synthesizer.chorusGain = data[1];\n break;\n \n case workletMessageType.destroyWorklet:\n this.alive = false;\n this.synthesizer.destroySynthProcessor();\n delete this.synthesizer;\n delete this.sequencer.midiData;\n delete this.sequencer;\n break;\n \n default:\n util.SpessaSynthWarn(\"Unrecognized event:\", data);\n break;\n }\n }\n \n // noinspection JSUnusedGlobalSymbols\n /**\n * the audio worklet processing logic\n * @param inputs {Float32Array[][]} required by WebAudioAPI\n * @param outputs {Float32Array[][]} the outputs to write to, only the first two channels are populated\n * @returns {boolean} true unless it's not alive\n */\n process(inputs, outputs)\n {\n if (!this.alive)\n {\n return false;\n }\n // process sequencer\n this.sequencer.processTick();\n \n if (this.oneOutputMode)\n {\n const out = outputs[0];\n // 1 output with 32 channels.\n // channels are ordered as follows:\n // midiChannel1L, midiChannel1R,\n // midiChannel2L, midiChannel2R\n // and so on\n /**\n * @type {Float32Array[][]}\n */\n const channelMap = [];\n for (let i = 0; i < 32; i += 2)\n {\n channelMap.push([out[i], out[i + 1]]);\n }\n this.synthesizer.renderAudioSplit(\n [], [], // effects are disabled\n channelMap\n );\n }\n else\n {\n // 18 outputs, each a stereo one\n // 0: reverb\n // 1: chorus\n // 2: channel 1\n // 3: channel 2\n // and so on\n this.synthesizer.renderAudioSplit(\n outputs[0], // reverb\n outputs[1], // chorus\n outputs.slice(2)\n );\n }\n return true;\n }\n}\n\n// noinspection JSUnresolvedReference\nregisterProcessor(WORKLET_PROCESSOR_NAME, WorkletSpessaProcessor);\nutil.SpessaSynthInfo(\"%cProcessor successfully registered!\", consoleColors.recognized);"],
5
- "mappings": "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",
6
- "names": ["ENABLE_INFO", "ENABLE_WARN", "ENABLE_GROUP", "ENABLE_TABLE", "SpessaSynthLogging", "enableInfo", "enableWarn", "enableGroup", "enableTable", "SpessaSynthInfo", "message", "SpessaSynthWarn", "SpessaSynthGroup", "SpessaSynthGroupCollapsed", "SpessaSynthGroupEnd", "formatTime", "totalSeconds", "minutes", "seconds", "formatTitle", "fileName", "arrayToHexString", "arr", "hexString", "i", "hex", "sanitizeKarLyrics", "eventData", "sanitized", "byte", "consoleColors", "getPriority", "channel", "voice", "priority", "voiceKilling", "amount", "allVoices", "a", "b", "voicesToRemove", "index", "DEFAULT_SYNTH_MODE", "stbvorbis", "isReady", "readySolver", "A", "atob", "I", "g", "B", "E", "Q", "C", "i", "h", "o", "G", "D", "a", "S", "F", "R", "s", "w", "y", "c", "n", "U", "$", "e", "t", "k", "N", "r", "__require", "Y", "J", "_", "II", "f", "H", "L", "M", "AN", "Ae", "d", "q", "K", "l", "u", "b", "X", "m", "Z", "V", "x", "p", "W", "IE", "T", "v", "IA", "A9", "A5", "Ai", "O", "j", "Ag", "P", "Ax", "Ap", "A6", "AV", "z", "AA", "A8", "AI", "A0", "AQ", "AB", "AE", "AC", "Ah", "Ao", "AG", "AD", "Aa", "AS", "AF", "AR", "As", "Aw", "Ay", "Ac", "An", "AU", "A$", "Az", "Ak", "Ar", "AY", "AJ", "Af", "AH", "AL", "AM", "Ad", "Aq", "AK", "Al", "Au", "Ab", "AX", "Am", "AZ", "A7", "A1", "AW", "A_", "AT", "A2", "Av", "AO", "Aj", "AP", "A4", "A3", "Ig", "IB", "timecentLookupTable", "i", "timecents", "timecentsToSeconds", "MIN_ABS_CENT", "MAX_ABS_CENT", "absoluteCentLookupTable", "absoluteCents", "absCentsToHz", "cents", "MIN_DECIBELS", "MAX_DECIBELS", "decibelLookUpTable", "decibels", "decibelAttenuationToGain", "generatorTypes", "generatorLimits", "Generator", "type", "value", "validate", "lim", "addAndClampGenerator", "generatorType", "presetGens", "instrumentGens", "limits", "presetGen", "g", "presetValue", "instruGen", "instruValue", "VOLUME_ENVELOPE_SMOOTHING_FACTOR", "DB_SILENCE", "PERCEIVED_DB_SILENCE", "PERCEIVED_GAIN_SILENCE", "VolumeEnvelope", "_VolumeEnvelope", "sampleRate", "initialDecay", "voice", "decibelAttenuationToGain", "env", "timecentsToSamples", "tc", "timecentsToSeconds", "generatorTypes", "sustainDb", "fullChange", "keyNumAddition", "fraction", "holdExcursion", "elapsed", "releaseFraction", "audioBuffer", "centibelOffset", "smoothingFactor", "decibelOffset", "attenuationSmoothing", "elapsedRelease", "i", "dbDifference", "db", "filledBuffer", "linearAttenuation", "IndexedByteArray", "args", "start", "end", "a", "combineArrays", "arrs", "length", "sum", "current", "newArr", "offset", "arr", "MIDIMessage", "ticks", "byte", "data", "getChannel", "statusByte", "eventType", "channel", "resultChannel", "messageTypes", "getEvent", "status", "eventChannel", "eventStatus", "midiControllers", "dataBytesAmount", "XG_SFX_VOICE", "GM2_DEFAULT_BANK", "getDefaultBank", "sys", "isXGDrums", "bankNr", "isValidXGMSB", "bank", "parseBankSelect", "bankBefore", "system", "isLSB", "isDrums", "channelNumber", "out", "drumsStatus", "isSystemXG", "canSetBankSelect", "SpessaSynthInfo", "consoleColors", "chooseBank", "msb", "lsb", "isXG", "masterParameterType", "setMasterParameter", "type", "value", "pan", "SYNTHESIZER_GAIN", "readBytesAsString", "dataArray", "bytes", "encoding", "trimEnd", "byteBuffer", "finished", "string", "i", "byte", "getStringBytes", "padLength", "len", "arr", "IndexedByteArray", "writeStringAsBytes", "getStringBytesZero", "outArray", "interpolationTypes", "synthDisplayTypes", "getTuning", "byte1", "byte2", "byte3", "midiNote", "fraction", "systemExclusive", "messageData", "channelOffset", "type", "SpessaSynthWarn", "arrayToHexString", "consoleColors", "cents", "vol", "SpessaSynthInfo", "pan", "masterParameterType", "tuningValue", "currentMessageIndex", "program", "tuningName", "readBytesAsString", "i", "tuningProgram", "numberOfChanges", "newOctaveTuning", "tuning", "notRecognized", "messageValue", "channel", "channelObject", "isDrums", "keyShift", "panpot", "midiControllers", "tuningBytes", "newTuning", "transpose", "text", "synthDisplayTypes", "dotMatrixData", "isSystemXG", "value", "semitones", "textData", "modulatorSources", "modulatorCurveTypes", "Modulator", "_Modulator", "srcEnum", "secSrcEnum", "destination", "amount", "transformType", "generatorTypes", "modulator", "mod1", "mod2", "checkAmount", "mod", "getKeyByValue", "object", "value", "key", "sourceString", "midiControllers", "secSrcString", "DEFAULT_ATTENUATION_MOD_AMOUNT", "DEFAULT_ATTENUATION_MOD_CURVE_TYPE", "getModSourceEnum", "curveType", "polarity", "direction", "isCC", "index", "soundFontModulators", "customModulators", "defaultModulators", "NON_CC_INDEX_OFFSET", "CONTROLLER_TABLE_SIZE", "resetArray", "setResetValue", "i", "v", "midiControllers", "PORTAMENTO_CONTROL_UNSET", "modulatorSources", "customControllers", "CUSTOM_CONTROLLER_TABLE_SIZE", "customResetArray", "dataEntryStates", "channelConfiguration", "resetAllControllers", "log", "SpessaSynthInfo", "consoleColors", "DEFAULT_SYNTH_MODE", "channelNumber", "ch", "getDefaultBank", "presetBank", "sentBank", "ccNum", "NON_CC_INDEX_OFFSET", "modulatorSources", "val", "msb", "lsb", "i", "resetControllers", "resetArray", "resetValue", "midiControllers", "PORTAMENTO_CONTROL_UNSET", "transpose", "customControllers", "customResetArray", "nonResetableCCs", "resetControllersRP15Compliant", "resetParameters", "dataEntryStates", "readLittleEndian", "dataArray", "bytesAmount", "out", "i", "writeLittleEndian", "number", "byteTarget", "writeWord", "word", "writeDword", "dword", "signedInt16", "byte1", "byte2", "val", "signedInt8", "byte", "RiffChunk", "header", "size", "data", "readRIFFChunk", "dataArray", "readData", "forceShift", "readBytesAsString", "readLittleEndian", "chunkData", "IndexedByteArray", "writeRIFFChunk", "chunk", "prepend", "array", "writeStringAsBytes", "writeDword", "writeRIFFOddSize", "addZeroByte", "isList", "tempData", "offset", "finalSize", "writtenSize", "headerWritten", "outArray", "findRIFFListType", "collection", "type", "c", "getIGEN", "igensize", "inst", "sum", "z", "g", "generatorTypes", "Generator", "igendata", "IndexedByteArray", "igenIndex", "instrument", "instrumentZone", "gen", "writeWord", "writeDword", "writeRIFFChunk", "RiffChunk", "getSDTA", "smplStartOffsets", "smplEndOffsets", "compress", "quality", "vorbisFunc", "sampleDatas", "s", "i", "r", "SpessaSynthInfo", "consoleColors", "smplSize", "total", "smplData", "IndexedByteArray", "sample", "data", "startOffset", "endOffset", "jump", "smplChunk", "writeRIFFChunk", "RiffChunk", "getSHDR", "smplStartOffsets", "smplEndOffsets", "shdrData", "IndexedByteArray", "sample", "index", "writeStringAsBytes", "dwStart", "writeDword", "dwEnd", "loopStart", "loopEnd", "writeWord", "writeRIFFChunk", "RiffChunk", "getIMOD", "imodsize", "inst", "sum", "z", "imoddata", "IndexedByteArray", "imodIndex", "ibag", "mod", "writeWord", "writeLittleEndian", "writeRIFFChunk", "RiffChunk", "getIBAG", "ibagsize", "sum", "i", "ibagdata", "IndexedByteArray", "zoneID", "generatorIndex", "modulatorIndex", "inst", "ibag", "writeWord", "writeRIFFChunk", "RiffChunk", "getINST", "instsize", "instdata", "IndexedByteArray", "instrumentStart", "instrumentID", "inst", "writeStringAsBytes", "writeWord", "writeRIFFChunk", "RiffChunk", "getPGEN", "pgensize", "preset", "size", "z", "g", "generatorTypes", "Generator", "pgendata", "IndexedByteArray", "pgenIndex", "presetZone", "gen", "writeWord", "writeRIFFChunk", "RiffChunk", "getPMOD", "pmodsize", "preset", "sum", "z", "pmoddata", "IndexedByteArray", "pmodIndex", "pbag", "mod", "writeWord", "writeLittleEndian", "writeRIFFChunk", "RiffChunk", "getPBAG", "pbagsize", "sum", "i", "pbagdata", "IndexedByteArray", "zoneID", "generatorIndex", "modulatorIndex", "preset", "pbag", "writeWord", "writeRIFFChunk", "RiffChunk", "getPHDR", "phdrsize", "phdrdata", "IndexedByteArray", "presetStart", "preset", "writeStringAsBytes", "writeWord", "writeDword", "writeRIFFChunk", "RiffChunk", "DEFAULT_WRITE_OPTIONS", "write", "options", "SpessaSynthGroupCollapsed", "consoleColors", "SpessaSynthInfo", "infoArrays", "type", "data", "major", "minor", "ckdata", "IndexedByteArray", "writeWord", "writeRIFFChunk", "RiffChunk", "arr", "writeStringAsBytes", "combined", "combineArrays", "infoChunk", "smplStartOffsets", "smplEndOffsets", "sdtaChunk", "getSDTA", "shdrChunk", "getSHDR", "igenChunk", "getIGEN", "imodChunk", "getIMOD", "ibagChunk", "getIBAG", "instChunk", "getINST", "pgenChunk", "getPGEN", "pmodChunk", "getPMOD", "pbagChunk", "getPBAG", "phdrChunk", "getPHDR", "pdtadata", "pdtaChunk", "riffdata", "main", "SpessaSynthGroupEnd", "BasicZone", "generatorType", "notFoundValue", "g", "BasicInstrumentZone", "BasicZone", "BasicPresetZone", "notGlobalizedTypes", "generatorTypes", "combineZones", "preset", "globalize", "addUnique", "main", "adder", "g", "mg", "subtractRanges", "r1", "r2", "addUniqueMods", "m", "mm", "Modulator", "finalZones", "globalPresetGenerators", "globalPresetModulators", "globalPresetKeyRange", "globalPresetVelRange", "globalPresetZone", "z", "presetZone", "presetZoneKeyRange", "presetZoneVelRange", "presetGenerators", "Generator", "presetModulators", "iZones", "globalInstGenerators", "globalInstModulators", "globalInstKeyRange", "globalInstVelRange", "globalInstZone", "instZone", "instZoneKeyRange", "instZoneVelRange", "instGenerators", "instModulators", "finalModList", "mod", "identicalInstMod", "finalGenList", "gen", "identicalInstGen", "newAmount", "generatorLimits", "zone", "BasicInstrumentZone", "globalZone", "checkedType", "occurencesForValues", "defaultForChecked", "value", "relativeCounterpart", "valueToGlobalize", "max", "curr", "targetValue", "modulators", "checkedModulator", "existsForAllZones", "modulator", "WSMP_SIZE", "writeWavesample", "sample", "rootKey", "tuning", "attenuationCentibels", "loopStart", "loopEnd", "loopingMode", "loopCount", "wsmpData", "IndexedByteArray", "writeDword", "writeWord", "attenuationCb", "lGain", "loopSize", "ulLoopType", "writeRIFFOddSize", "DLSSources", "DEFAULT_DLS_REVERB", "Modulator", "generatorTypes", "DEFAULT_DLS_CHORUS", "DLS_1_NO_VIBRATO_MOD", "DLS_1_NO_VIBRATO_PRESSURE", "DLSDestinations", "Articulator", "source", "control", "destination", "scale", "transform", "out", "IndexedByteArray", "writeWord", "writeDword", "getDLSSourceFromSf2Source", "cc", "index", "midiControllers", "DLSSources", "modulatorSources", "getDLSDestinationFromSf2", "dest", "amount", "generatorTypes", "DLSDestinations", "checkSF2SpecialCombos", "amt", "getDLSArticulatorFromSf2Generator", "gen", "destination", "source", "combo", "SpessaSynthWarn", "Articulator", "getDLSArticulatorFromSf2Modulator", "mod", "sourceTransformType", "sourceBipolar", "sourceDirection", "control", "controlTransformType", "controlBipolar", "controlDirection", "dlsDestinationFromSf2", "specialCombo", "modulatorCurveTypes", "transform", "invalidGeneratorTypes", "generatorTypes", "writeArticulator", "zone", "i", "g", "Generator", "relativeGenerator", "absoluteCounterpart", "absoluteGenerator", "dlsRelative", "subtraction", "newAbsolute", "iR", "iA", "generators", "arrs", "art", "getDLSArticulatorFromSf2Generator", "SpessaSynthInfo", "consoleColors", "SpessaSynthWarn", "modulators", "m", "Modulator", "DEFAULT_DLS_CHORUS", "DEFAULT_DLS_REVERB", "DLS_1_NO_VIBRATO_MOD", "DLS_1_NO_VIBRATO_PRESSURE", "getDLSArticulatorFromSf2Modulator", "art2Data", "IndexedByteArray", "writeDword", "out", "a", "writeRIFFOddSize", "combineArrays", "writeDLSRegion", "zone", "globalZone", "rgnhData", "IndexedByteArray", "writeWord", "exclusive", "generatorTypes", "rgnh", "writeRIFFOddSize", "rootKey", "wsmp", "writeWavesample", "wlnkData", "writeDword", "wlnk", "lar2", "art2", "writeArticulator", "combineArrays", "writeIns", "preset", "SpessaSynthGroupCollapsed", "consoleColors", "combined", "combineZones", "nonGlobalRegionsCount", "sum", "z", "inshData", "IndexedByteArray", "writeDword", "ulBank", "insh", "writeRIFFOddSize", "lar2", "globalZone", "art2", "writeArticulator", "lrgnData", "combineArrays", "arrs", "writeDLSRegion", "lrgn", "inam", "getStringBytesZero", "info", "SpessaSynthGroupEnd", "writeLins", "lins", "combineArrays", "p", "writeIns", "writeRIFFOddSize", "writeDLSSample", "sample", "fmtData", "IndexedByteArray", "writeWord", "writeDword", "fmt", "writeRIFFOddSize", "loop", "wsmp", "writeWavesample", "audio", "data", "data16", "i", "inam", "getStringBytesZero", "info", "SpessaSynthInfo", "consoleColors", "combineArrays", "writeWavePool", "currentIndex", "offsets", "samples", "s", "out", "writeDLSSample", "writeRIFFOddSize", "combineArrays", "writeDLS", "SpessaSynthGroupCollapsed", "consoleColors", "colhNum", "IndexedByteArray", "writeDword", "colh", "writeRIFFOddSize", "lins", "writeLins", "SpessaSynthInfo", "SpessaSynthGroupEnd", "wavepool", "writeWavePool", "wvpl", "ptblOffsets", "ptblData", "offset", "ptbl", "infos", "info", "data", "getStringBytesZero", "combineArrays", "out", "writeStringAsBytes", "RESAMPLE_RATE", "BasicSample", "sampleName", "sampleRate", "samplePitch", "samplePitchCorrection", "sampleLink", "sampleType", "loopStart", "loopEnd", "uint8", "i", "sample", "newSampleRate", "audioData", "ratio", "resampled", "quality", "encodeVorbis", "SpessaSynthWarn", "BasicInstrument", "z", "i", "index", "BasicPreset", "parentSoundBank", "i", "allowXG", "allowSFX", "xg", "isXGDrums", "z", "index", "keyMin", "keyMax", "key", "velocity", "samandgen", "midiNote", "memorized", "isInRange", "range", "number", "addUnique", "main", "adder", "g", "mg", "addUniqueMods", "m", "mm", "Modulator", "parsedGeneratorsAndSamples", "globalPresetGenerators", "globalPresetModulators", "globalKeyRange", "globalVelRange", "currentZone", "zone", "presetGenerators", "presetModulators", "firstZone", "globalInstrumentGenerators", "globalInstrumentModulators", "instrumentZone", "instrumentGenerators", "instrumentModulators", "finalModulatorList", "mod", "identicalInstrumentModulator", "generatorTypes", "BasicSoundBank", "_BasicSoundBank", "defaultModulators", "m", "Modulator", "data", "soundfonts", "mainSf", "presets", "newPreset", "existingPreset", "font", "sample", "BasicSample", "i", "gZone", "BasicInstrumentZone", "Generator", "generatorTypes", "zone1", "zone2", "inst", "BasicInstrument", "pZone", "BasicPresetZone", "preset", "BasicPreset", "allowedPrograms", "isXGDrums", "SpessaSynthInfo", "consoleColors", "mid", "soundfont", "trimInstrumentZones", "instrument", "combos", "trimmedIZones", "iZoneIndex", "iZone", "iKeyRange", "iVelRange", "isIZoneUsed", "iCombo", "SpessaSynthGroup", "usedProgramsAndKeys", "SpessaSynthGroupCollapsed", "presetIndex", "p", "string", "used", "s", "split", "trimmedZones", "zoneIndex", "zone", "keyRange", "velRange", "isZoneUsed", "combo", "SpessaSynthGroupEnd", "z", "bankNr", "programNr", "allowXGDrums", "isDrum", "isDrums", "SpessaSynthWarn", "presetName", "error", "write", "writeDLS", "readDLSInstrumentList", "instrumentListChunk", "SpessaSynthGroupCollapsed", "consoleColors", "i", "readRIFFChunk", "SpessaSynthGroupEnd", "DLSPreset", "BasicPreset", "dls", "ulBank", "ulInstrument", "bankMSB", "bankLSB", "BasicInstrument", "zone", "BasicPresetZone", "readDLSInstrument", "chunk", "readBytesAsString", "chunks", "readRIFFChunk", "instrumentHeader", "c", "SpessaSynthGroupEnd", "regions", "readLittleEndian", "ulBank", "ulInstrument", "preset", "DLSPreset", "presetName", "infoChunk", "findRIFFListType", "info", "SpessaSynthGroupCollapsed", "consoleColors", "regionListChunk", "globalZone", "BasicInstrumentZone", "globalLart", "globalLar2", "g", "generatorLimits", "m", "generatorTypes", "Modulator", "DEFAULT_DLS_REVERB", "DEFAULT_DLS_CHORUS", "i", "type", "zone", "getSF2SourceFromDLS", "source", "sourceEnum", "isCC", "DLSSources", "modulatorSources", "midiControllers", "getSF2GeneratorFromDLS", "destination", "amount", "DLSDestinations", "generatorTypes", "checkForSpecialDLSCombo", "getSF2ModulatorFromArticulator", "source", "control", "destination", "transform", "value", "specialDestination", "checkForSpecialDLSCombo", "destinationGenerator", "sf2Source", "swapSources", "isSourceNoController", "newValue", "sf2GenDestination", "getSF2GeneratorFromDLS", "SpessaSynthWarn", "getSF2SourceFromDLS", "modulatorSources", "sf2SecondSource", "sourceEnumFinal", "outputTransform", "sourceTransform", "modulatorCurveTypes", "sourceIsBipolar", "sourceIsNegative", "generatorTypes", "getModSourceEnum", "secSourceTransform", "secSourceIsBipolar", "secSourceIsNegative", "secSourceEnumFinal", "temp", "Modulator", "readArticulation", "chunk", "disableVibrato", "artData", "generators", "modulators", "readLittleEndian", "connectionsAmount", "i", "source", "control", "destination", "transform", "value", "generator", "DLSDestinations", "Generator", "generatorTypes", "sustainCb", "percentageSustain", "semi", "cents", "isGenerator", "applyKeyToCorrection", "keyToGen", "realGen", "keyToGenValue", "correction", "g", "DLSSources", "mod", "getSF2ModulatorFromArticulator", "SpessaSynthInfo", "consoleColors", "SpessaSynthWarn", "Modulator", "DLS_1_NO_VIBRATO_MOD", "DLS_1_NO_VIBRATO_PRESSURE", "readLart", "lartChunk", "lar2Chunk", "zone", "art1", "readRIFFChunk", "modsAndGens", "readArticulation", "art2", "DLSZone", "BasicInstrumentZone", "keyRange", "velRange", "attenuationCb", "loopingMode", "loop", "sampleKey", "sample", "sampleID", "samplePitchCorrection", "Generator", "generatorTypes", "coarseTune", "fineTune", "diffStart", "diffEnd", "fine", "coarse", "readRegion", "chunk", "regionChunks", "readRIFFChunk", "regionHeader", "c", "keyMin", "readLittleEndian", "keyMax", "velMin", "velMax", "zone", "DLSZone", "exclusive", "Generator", "generatorTypes", "lart", "findRIFFListType", "lar2", "waveSampleChunk", "originalKey", "pitchCorrection", "signedInt16", "dbCorrection", "loopsAmount", "loopingMode", "loop", "loopLength", "waveLinkChunk", "sampleID", "sample", "attenuation", "DLSSample", "BasicSample", "name", "rate", "pitch", "pitchCorrection", "loopStart", "loopEnd", "data", "sampleDbAttenuation", "W_FORMAT_TAG", "readPCM", "dataChunk", "bytesPerSample", "maxSampleValue", "maxUnsigned", "normalizationFactor", "isUnsigned", "sampleLength", "sampleData", "sample", "readLittleEndian", "readALAW", "i", "input", "exponent", "mantissa", "s16sample", "readDLSSamples", "waveListChunk", "SpessaSynthGroupCollapsed", "consoleColors", "sampleID", "waveChunk", "readRIFFChunk", "readBytesAsString", "waveChunks", "fmtChunk", "c", "waveFormat", "channelsAmount", "sampleRate", "failed", "waveInfo", "findRIFFListType", "sampleName", "infoChunk", "sampleKey", "samplePitch", "sampleLoopStart", "sampleLoopEnd", "sampleDbAttenuation", "wsmpChunk", "signedInt16", "samplePitchSemitones", "loopSize", "SpessaSynthWarn", "DLSSample", "SpessaSynthInfo", "SpessaSynthGroupEnd", "DLSSoundFont", "BasicSoundBank", "buffer", "IndexedByteArray", "SpessaSynthGroup", "consoleColors", "SpessaSynthGroupEnd", "firstChunk", "readRIFFChunk", "readBytesAsString", "chunks", "infoChunk", "findRIFFListType", "infoPart", "info", "value", "SpessaSynthInfo", "colhChunk", "c", "readLittleEndian", "waveListChunk", "instrumentListChunk", "a", "b", "chunk", "expected", "expect", "text", "error", "readDLSInstrumentList", "readDLSInstrument", "readRegion", "readLart", "readDLSSamples", "SoundFontSample", "BasicSample", "sampleName", "sampleStartIndex", "sampleEndIndex", "sampleLoopStartIndex", "sampleLoopEndIndex", "sampleRate", "samplePitch", "samplePitchCorrection", "sampleLink", "sampleType", "smplArr", "sampleIndex", "isDataRaw", "smplStart", "dataStartIndex", "buff", "vorbis", "stbvorbis", "SpessaSynthWarn", "e", "audioData", "convertedSigned16", "i", "readSamples", "sampleHeadersChunk", "smplChunkData", "isSmplDataRaw", "samples", "index", "sample", "readSample", "sampleHeaderData", "smplArrayData", "readBytesAsString", "readLittleEndian", "signedInt8", "ReadGenerator", "Generator", "dataArray", "i", "signedInt16", "readGenerators", "generatorChunk", "gens", "InstrumentZone", "BasicInstrumentZone", "dataArray", "readLittleEndian", "modulatorZoneSize", "generatorZoneSize", "generators", "i", "modulators", "samples", "sampleID", "g", "generatorTypes", "range", "readInstrumentZones", "zonesChunk", "instrumentGenerators", "instrumentModulators", "instrumentSamples", "zones", "zone", "PresetZone", "BasicPresetZone", "instruments", "instrumentID", "readPresetZones", "presetGenerators", "presetModulators", "Preset", "BasicPreset", "presetChunk", "sf2", "readBytesAsString", "readLittleEndian", "amount", "zones", "i", "readPresets", "presetZones", "presets", "preset", "presetZonesAmount", "Instrument", "BasicInstrument", "instrumentChunk", "readBytesAsString", "readLittleEndian", "amount", "zones", "i", "readInstruments", "instrumentZones", "instruments", "instrument", "instrumentsAmount", "ReadModulator", "Modulator", "dataArray", "srcEnum", "readLittleEndian", "destination", "amount", "signedInt16", "secSrcEnum", "transformType", "readModulators", "modulatorChunk", "gens", "SoundFont2", "BasicSoundBank", "arrayBuffer", "warnDeprecated", "IndexedByteArray", "SpessaSynthGroup", "consoleColors", "SpessaSynthGroupEnd", "firstChunk", "readRIFFChunk", "type", "readBytesAsString", "isSF2Pack", "infoChunk", "chunk", "text", "readLittleEndian", "newModulators", "readModulators", "oldDefaults", "m", "mm", "Modulator", "SpessaSynthInfo", "sdtaChunk", "sampleDataChunk", "sampleData", "stbvorbis", "e", "presetChunk", "presetHeadersChunk", "presetZonesChunk", "presetModulatorsChunk", "presetGeneratorsChunk", "presetInstrumentsChunk", "presetInstrumentZonesChunk", "presetInstrumentModulatorsChunk", "presetInstrumentGeneratorsChunk", "presetSamplesChunk", "readSamples", "instrumentGenerators", "readGenerators", "instrumentModulators", "instrumentZones", "readInstrumentZones", "readInstruments", "presetGenerators", "presetModulators", "presetZones", "readPresetZones", "readPresets", "a", "b", "expected", "loadSoundFont", "buffer", "check", "a", "IndexedByteArray", "readBytesAsString", "DLSSoundFont", "SoundFont2", "SoundFontManager", "initialSoundFontBuffer", "presetList", "i", "font", "presets", "p", "presetString", "string", "name", "pb", "soundFontArrayBuffer", "loadSoundFont", "id", "SpessaSynthWarn", "index", "s", "buffer", "bankOffset", "newList", "a", "b", "bankNumber", "programNumber", "allowXGDrums", "sf", "preset", "isXGDrums", "KeyModifierManager", "channel", "midiNote", "mapping", "mappings", "bank", "modifier", "FILTER_SMOOTHING_FACTOR", "LowpassFilter", "_LowpassFilter", "sampleRate", "voice", "outputBuffer", "fcExcursion", "smoothingFactor", "initialFc", "generatorTypes", "filter", "targetCutoff", "modulatedResonance", "i", "input", "filtered", "cutoffCents", "qCb", "cached", "cutoffHz", "absCentsToHz", "qDb", "resonanceGain", "decibelAttenuationToGain", "qGain", "w", "cosw", "alpha", "b1", "b0", "b2", "a0", "a1", "a2", "toCache", "dummy", "MOD_PRECOMPUTED_LENGTH", "concave", "convex", "i", "x", "getModulatorCurveValue", "direction", "curveType", "value", "polarity", "modulatorCurveTypes", "MODENV_PEAK", "CONVEX_ATTACK", "i", "getModulatorCurveValue", "modulatorCurveTypes", "ModulationEnvelope", "_ModulationEnvelope", "voice", "env", "generatorTypes", "timecentsToSeconds", "decayKeyExcursionCents", "decayTime", "holdKeyExcursionCents", "releaseTime", "currentTime", "ignoreRelease", "EXCLUSIVE_CUTOFF_TIME", "EXCLUSIVE_MOD_CUTOFF_TIME", "AudioSample", "data", "playbackStep", "cursorStart", "rootKey", "loopStart", "loopEnd", "endIndex", "loopingMode", "Voice", "_Voice", "ModulationEnvelope", "sampleRate", "audioSample", "midiNote", "velocity", "channel", "currentTime", "targetKey", "realKey", "generators", "modulators", "generatorTypes", "LowpassFilter", "VolumeEnvelope", "voice", "sampleToCopy", "sample", "m", "Modulator", "MIN_EXCLUSIVE_LENGTH", "minNoteLength", "MIN_NOTE_LENGTH", "getVoices", "voices", "channelObject", "overridePatch", "bank", "program", "override", "cached", "v", "preset", "isSystemXG", "sampleAndGenerators", "SpessaSynthWarn", "i", "addAndClampGenerator", "PAN_SMOOTHING_FACTOR", "REVERB_DIVIDER", "CHORUS_DIVIDER", "HALF_PI", "MIN_PAN", "MAX_PAN", "PAN_RESOLUTION", "panTableLeft", "panTableRight", "pan", "realPan", "tableIndex", "panVoice", "voice", "inputBuffer", "outputLeft", "outputRight", "reverbLeft", "reverbRight", "chorusLeft", "chorusRight", "generatorTypes", "gain", "index", "gainLeft", "gainRight", "reverbSend", "reverbGain", "i", "chorusSend", "chorusGain", "chorusLeftGain", "chorusRightGain", "stopAllChannels", "force", "SpessaSynthInfo", "consoleColors", "i", "setEmbeddedSoundFont", "font", "offset", "s", "reloadSoundFont", "buffer", "isOverride", "loadSoundFont", "c", "SpessaSynthInfo", "consoleColors", "clearSoundFont", "sendPresets", "clearOverride", "i", "channelObject", "sendPresetList", "mainFont", "p", "bankCheck", "exists", "pr", "getPreset", "bank", "program", "bankWithOffset", "preset", "isSystemXG", "transposeAllChannels", "semitones", "force", "i", "setMasterTuning", "cents", "i", "customControllers", "ChannelSnapshot", "_ChannelSnapshot", "spessaSynthProcessor", "channelNumber", "channelObject", "channelSnapshot", "SynthesizerSnapshot", "_SynthesizerSnapshot", "spessaSynthProcessor", "snapshot", "_", "i", "ChannelSnapshot", "masterParameterType", "channelSnapshot", "index", "SpessaSynthInfo", "consoleColors", "applySynthesizerSnapshot", "snapshot", "SynthesizerSnapshot", "SpessaSynthInfo", "consoleColors", "getLFOValue", "startTime", "frequency", "currentTime", "xVal", "WavetableOscillator", "voice", "outputBuffer", "sample", "cur", "sampleData", "loopLength", "i", "floor", "ceil", "fraction", "upper", "lower", "y0", "y1", "y2", "y3", "t", "x0", "x1", "x2", "x3", "c1", "c2", "c3", "renderVoice", "voice", "timeNow", "outputLeft", "outputRight", "reverbOutputLeft", "reverbOutputRight", "chorusOutputLeft", "chorusOutputRight", "VolumeEnvelope", "ModulationEnvelope", "generatorTypes", "targetKey", "cents", "semitones", "tuning", "elapsed", "diff", "vibratoDepth", "vibStart", "timecentsToSeconds", "vibFreqHz", "absCentsToHz", "lfoVal", "getLFOValue", "customControllers", "lowpassExcursion", "modPitchDepth", "modVolDepth", "modFilterDepth", "modLfoCentibels", "modStart", "modFreqHz", "modLfoValue", "channelVibrato", "modEnvPitchDepth", "modEnvFilterDepth", "modEnv", "centsTotal", "bufferOut", "interpolationTypes", "WavetableOscillator", "LowpassFilter", "killNote", "midiNote", "releaseTime", "v", "generatorTypes", "setTuning", "cents", "log", "customControllers", "SpessaSynthInfo", "consoleColors", "setModulationDepth", "cents", "SpessaSynthInfo", "consoleColors", "customControllers", "dataEntryFine", "dataValue", "dataEntryStates", "midiControllers", "NON_CC_INDEX_OFFSET", "modulatorSources", "actualTune", "SpessaSynthInfo", "consoleColors", "finalTuning", "customControllers", "cents", "EFFECT_MODULATOR_TRANSFORM_MULTIPLIER", "computeModulator", "controllerTable", "modulator", "voice", "rawSourceValue", "index", "NON_CC_INDEX_OFFSET", "modulatorSources", "sourceValue", "transforms", "rawSecondSrcValue", "secondSrcValue", "transformAmount", "computedValue", "computeModulators", "sourceUsesCC", "sourceIndex", "modulators", "generators", "modulatedGenerators", "mod", "limits", "generatorLimits", "newValue", "VolumeEnvelope", "ModulationEnvelope", "volenvNeedsRecalculation", "generatorTypes", "computedDestinations", "destination", "m", "dest", "curve", "MOD_PRECOMPUTED_LENGTH", "i", "getModulatorCurveValue", "controllerChange", "controllerNumber", "controllerValue", "force", "channelConfiguration", "midiControllers", "actualCCNum", "v", "computeModulators", "dataEntryStates", "stopAllNotes", "force", "v", "muteChannel", "isMuted", "transposeChannel", "semitones", "force", "keyShift", "currentTranspose", "customControllers", "midiControllers", "registeredParameterTypes", "nonRegisteredParameterNumbers", "dataEntryCoarse", "dataValue", "addDefaultVibrato", "coolInfo", "what", "value", "type", "SpessaSynthInfo", "consoleColors", "dataEntryStates", "NRPNCoarse", "midiControllers", "NRPNFine", "SpessaSynthWarn", "reverb", "rpnValue", "NON_CC_INDEX_OFFSET", "modulatorSources", "semitones", "customControllers", "portamentoLookup", "getLookup", "value", "lower", "upper", "key", "lowerTime", "upperTime", "portamentoTimeToSeconds", "time", "distance", "noteOn", "midiNote", "velocity", "realKey", "sentMidiNote", "program", "tune", "keyVel", "voiceGain", "portamentoFromKey", "portamentoDuration", "portamentoTime", "midiControllers", "control", "currentFromKey", "diff", "portamentoTimeToSeconds", "voices", "panOverride", "channelVoices", "voice", "exclusive", "v", "computeModulators", "cursorStartOffset", "generatorTypes", "endOffset", "loopStartOffset", "loopEndOffset", "sm", "clamp", "num", "temp", "noteOff", "midiNote", "SpessaSynthWarn", "realKey", "v", "polyPressure", "midiNote", "pressure", "v", "computeModulators", "modulatorSources", "channelPressure", "pressure", "NON_CC_INDEX_OFFSET", "modulatorSources", "v", "computeModulators", "pitchWheel", "MSB", "LSB", "NON_CC_INDEX_OFFSET", "modulatorSources", "bend", "v", "computeModulators", "setOctaveTuning", "tuning", "i", "programChange", "programNumber", "bank", "sentBank", "preset", "isXG", "bankWithOffset", "p", "offset", "s", "MidiAudioChannel", "CONTROLLER_TABLE_SIZE", "CUSTOM_CONTROLLER_TABLE_SIZE", "dataEntryStates", "synth", "preset", "channelNumber", "isSystemXG", "type", "value", "customControllers", "outputLeft", "outputRight", "reverbOutputLeft", "reverbOutputRight", "chorusOutputLeft", "chorusOutputRight", "v", "locked", "bank", "isLSB", "parseBankSelect", "chooseBank", "isDrum", "depth", "rate", "delay", "data", "NON_CC_INDEX_OFFSET", "modulatorSources", "renderVoice", "panVoice", "killNote", "stopAllNotes", "muteChannel", "noteOn", "noteOff", "polyPressure", "channelPressure", "pitchWheel", "programChange", "setTuning", "setOctaveTuning", "setModulationDepth", "transposeChannel", "controllerChange", "resetControllers", "resetControllersRP15Compliant", "resetParameters", "dataEntryFine", "dataEntryCoarse", "createMidiChannel", "sendEvent", "channel", "MidiAudioChannel", "MIN_NOTE_LENGTH", "MIN_EXCLUSIVE_LENGTH", "SYNTHESIZER_GAIN", "SpessaSynthProcessor", "interpolationTypes", "KeyModifierManager", "DEFAULT_SYNTH_MODE", "stbvorbis", "soundfont", "sampleRate", "callbacks", "effectsEnabled", "enableEventSystem", "initialTime", "midiChannels", "snapshot", "initialChannelCount", "i", "SoundFontManager", "VOLUME_ENVELOPE_SMOOTHING_FACTOR", "PAN_SMOOTHING_FACTOR", "FILTER_SMOOTHING_FACTOR", "sys", "value", "masterParameterType", "bank", "program", "midiNote", "velocity", "voices", "SpessaSynthInfo", "consoleColors", "outputs", "reverb", "chorus", "reverbChannels", "chorusChannels", "separateChannels", "time", "revL", "revR", "chrL", "chrR", "channel", "index", "voiceCount", "ch", "c", "controllerNumber", "controllerValue", "force", "pressure", "MSB", "LSB", "programNumber", "message", "channelOffset", "options", "call", "statusByteData", "getEvent", "messageTypes", "IndexedByteArray", "e1", "e2", "volume", "eventName", "eventData", "voiceKilling", "getVoices", "systemExclusive", "stopAllChannels", "createMidiChannel", "resetAllControllers", "setMasterParameter", "transposeAllChannels", "setMasterTuning", "getPreset", "reloadSoundFont", "clearSoundFont", "setEmbeddedSoundFont", "sendPresetList", "applySynthesizerSnapshot", "readBytesAsUintBigEndian", "dataArray", "bytesAmount", "out", "i", "writeBytesAsUintBigEndian", "number", "bytes", "_processEvent", "event", "trackIndex", "statusByteData", "getEvent", "offset", "messageTypes", "velocity", "toDelete", "n", "tempoBPM", "readBytesAsUintBigEndian", "SpessaSynthWarn", "k", "consoleColors", "_addNewMidiPort", "i", "processTick", "current", "trackIndex", "event", "eventNext", "canLoop", "_findFirstEventIndex", "index", "ticks", "track", "i", "MIDISequenceData", "ticks", "totalSeconds", "tempo", "v", "timeSinceLastTempo", "sequence", "arr", "set", "readVariableLengthQuantity", "MIDIbyteArray", "out", "byte", "writeVariableLengthQuantity", "number", "bytes", "writeMIDI", "midi", "binaryTrackData", "track", "binaryTrack", "currentTick", "runningByte", "event", "deltaTicks", "messageData", "messageTypes", "writeVariableLengthQuantity", "writeText", "text", "arr", "i", "binaryData", "writeBytesAsUintBigEndian", "isXGOn", "isGSDrumsOn", "isGSOn", "isGMOn", "isGM2On", "getGsOn", "ticks", "MIDIMessage", "messageTypes", "IndexedByteArray", "getControllerChange", "channel", "cc", "value", "getDrumChange", "chanAddress", "sysexData", "checksum", "modifyMIDI", "desiredProgramChanges", "desiredControllerChanges", "desiredChannelsToClear", "desiredChannelsToTranspose", "midi", "SpessaSynthGroupCollapsed", "consoleColors", "SpessaSynthInfo", "channelsToChangeProgram", "c", "system", "addedGs", "eventIndexes", "remainingTracks", "findFirstEventIndex", "index", "track", "i", "midiPorts", "midiPortChannelOffsets", "midiPortChannelOffset", "assignMIDIPort", "trackNum", "port", "trackIndex", "channelsAmount", "isFirstNoteOn", "coarseTranspose", "fineTranspose", "transpose", "coarse", "fine", "e", "deleteThisEvent", "addEventBefore", "offset", "portOffset", "status", "midiChannel", "change", "ccChange", "fineTune", "centsCoarse", "rpnCoarse", "midiControllers", "rpnFine", "dataEntryCoarse", "dataEntryFine", "desiredBank", "desiredProgram", "programChange", "addBank", "isLSB", "v", "bankChange", "isSystemXG", "isXGDrums", "XG_SFX_VOICE", "ccNum", "isXGOn", "isGSOn", "isGMOn", "isGM2On", "SpessaSynthGroupEnd", "applySnapshotToMIDI", "snapshot", "channelsToTranspose", "channelsToClear", "programChanges", "controllerChanges", "channelNumber", "transposeFloat", "customControllers", "l", "ccNumber", "targetValue", "RMIDINFOChunks", "FORCED_ENCODING", "DEFAULT_COPYRIGHT", "writeRMIDI", "soundfontBinary", "soundfont", "bankOffset", "encoding", "metadata", "correctBankOffset", "mid", "SpessaSynthGroup", "consoleColors", "SpessaSynthInfo", "findFirstEventIndex", "index", "ticks", "track", "i", "eventIndexes", "system", "unwantedSystems", "remainingTracks", "ports", "channelsAmount", "max", "cur", "channelsInfo", "trackNum", "e", "portOffset", "messageTypes", "status", "isGSDrumsOn", "isXGOn", "isGSOn", "isGMOn", "isGM2On", "sysexChannel", "chNum", "channel", "isXG", "isSystemXG", "initialProgram", "p", "realBank", "bankLSB", "bank", "chooseBank", "targetBank", "drumBank", "newBank", "isLSB", "midiControllers", "bankNumber", "intepretation", "parseBankSelect", "has", "ch", "midiChannel", "port", "t", "tNum", "indexToAdd", "programIndex", "programTicks", "targetProgram", "MIDIMessage", "IndexedByteArray", "m", "getGsOn", "newMid", "infoContent", "getStringBytes", "encoder", "writeRIFFOddSize", "today", "getStringBytesZero", "copyright", "DBNK", "writeLittleEndian", "infodata", "combineArrays", "rmiddata", "SpessaSynthGroupEnd", "getUsedProgramsAndKeys", "soundfont", "mid", "SpessaSynthGroupCollapsed", "consoleColors", "channelsAmount", "max", "cur", "channelPresets", "i", "bank", "system", "updateString", "ch", "chooseBank", "isSystemXG", "exists", "usedProgramsAndKeys", "SpessaSynthInfo", "eventIndexes", "remainingTracks", "findFirstEventIndex", "index", "ticks", "track", "ports", "c", "trackNum", "event", "messageTypes", "status", "channel", "isLSB", "midiControllers", "realBank", "parseBankSelect", "isGSDrumsOn", "isXGOn", "sysexChannel", "isDrum", "key", "SpessaSynthGroupEnd", "getNoteTimes", "minDrumLength", "getTempo", "event", "IndexedByteArray", "readBytesAsUintBigEndian", "noteTimes", "events", "e1", "e2", "i", "elapsedTime", "oneTickToSeconds", "eventIndex", "unfinished", "unfinishedNotes", "noteOff", "midiNote", "channel", "noteIndex", "n", "note", "time", "status", "noteTime", "channelNotes", "BasicMIDI", "_BasicMIDI", "MIDISequenceData", "mid", "m", "track", "SpessaSynthGroup", "consoleColors", "karaokeHasTitle", "copyrightComponents", "copyrightDetected", "nameDetected", "loopStart", "loopEnd", "i", "usedChannels", "trackHasVoiceMessages", "e", "j", "messageTypes", "SpessaSynthInfo", "note", "eventText", "readBytesAsString", "readBytesAsUintBigEndian", "checkedText", "getStringBytes", "sanitizeKarLyrics", "trackName", "name", "firstNoteOns", "t", "firstNoteOn", "portOffset", "trackNum", "port", "defaultPort", "message", "formatTitle", "MIDIMessage", "IndexedByteArray", "SpessaSynthGroupEnd", "e1", "e2", "writeMIDI", "modifyMIDI", "applySnapshotToMIDI", "writeRMIDI", "getUsedProgramsAndKeys", "getNoteTimes", "assignMIDIPort", "trackNum", "port", "loadNewSequence", "parsedMidi", "autoPlay", "SpessaSynthInfo", "consoleColors", "SpessaSynthGroupCollapsed", "used", "programBank", "combos", "bank", "program", "preset", "combo", "split", "SpessaSynthGroupEnd", "trackIndex", "formatTime", "SpessaSynthWarn", "targetTime", "loadNewSongList", "midiBuffers", "m", "BasicMIDI", "nextSong", "previousSong", "defaultControllerArray", "resetArray", "_playTo", "time", "ticks", "channelsToSave", "pitchBends", "programs", "isCCNonSkippable", "controllerNumber", "midiControllers", "savedControllers", "resetAllControlllers", "chan", "i", "nonResetableCCs", "trackIndex", "event", "info", "getEvent", "channel", "messageTypes", "p", "ccV", "nextEvent", "channelNumber", "value", "index", "bank", "play", "resetTime", "n", "setTimeTicks", "isNotFinished", "_recalculateStartTime", "sendMIDIMessage", "message", "sendMIDICC", "channel", "type", "value", "messageTypes", "sendMIDIProgramChange", "program", "sendMIDIPitchWheel", "MSB", "LSB", "sendMIDIReset", "ch", "midiControllers", "SpessaSynthSequencer", "spessasynthProcessor", "value", "time", "wasPaused", "SpessaSynthWarn", "isFinished", "i", "midiControllers", "note", "messageTypes", "c", "autoPlay", "index", "indexes", "_", "sendMIDIMessage", "sendMIDIReset", "sendMIDICC", "sendMIDIProgramChange", "sendMIDIPitchWheel", "assignMIDIPort", "_processEvent", "_addNewMidiPort", "processTick", "_findFirstEventIndex", "loadNewSequence", "loadNewSongList", "nextSong", "previousSong", "play", "_playTo", "setTimeTicks", "_recalculateStartTime", "tr", "l", "T", "ur", "W", "X", "wr", "Y", "r", "a", "e", "f", "v", "g", "Z", "$", "cr", "j", "hr", "Fr", "_", "i", "c", "A", "k", "b", "m", "U", "x", "n", "o", "M", "L", "gr", "br", "q", "u", "C", "kr", "xr", "yr", "h", "Sr", "fr", "or", "lr", "S", "I", "z", "D", "G", "H", "N", "s", "d", "F", "P", "t", "rr", "Ar", "Mr", "ar", "w", "E", "O", "er", "y", "J", "K", "Ur", "zr", "Q", "p", "nr", "B", "R", "V", "vr", "ir", "Dr", "Tr", "mr", "Er", "pr", "metadataTypes", "referenceTypeIds", "resourceFormatIDs", "formatTypeIDs", "unpackerIDs", "XMFNode", "_XMFNode", "binaryData", "nodeStartIndex", "readVariableLengthQuantity", "headerLength", "readBytes", "remainingHeader", "headerData", "metadataChunk", "fieldSpecifier", "key", "SpessaSynthWarn", "k", "stringLength", "readBytesAsString", "numberOfVersions", "dataLength", "contentsChunk", "unpackersStart", "unpackersLength", "unpackersData", "unpacker", "SpessaSynthGroupEnd", "manufacturerID", "manufacturerInternalID", "compressed", "SpessaSynthInfo", "consoleColors", "IndexedByteArray", "tr", "e", "resourceFormat", "resourceFormatID", "nodeLength", "nodeData", "loadXMF", "midi", "sanityCheck", "SpessaSynthGroup", "version", "fileTypeId", "readBytesAsUintBigEndian", "fileTypeRevisionId", "metadataTableLength", "rootNode", "midiArray", "searchNode", "node", "checkMeta", "xmf", "rmid", "RMIDINFOChunks", "n", "MIDI", "BasicMIDI", "arrayBuffer", "fileName", "SpessaSynthGroupCollapsed", "consoleColors", "binaryData", "IndexedByteArray", "fileByteArray", "initialString", "readBytesAsString", "rmid", "SpessaSynthGroupEnd", "riff", "readRIFFChunk", "startIndex", "currentChunk", "type", "SpessaSynthInfo", "SpessaSynthWarn", "infoChunk", "RMIDINFOChunks", "readLittleEndian", "loadXMF", "headerChunk", "readBytesAsUintBigEndian", "i", "track", "trackChunk", "runningByte", "totalTicks", "readVariableLengthQuantity", "statusByteCheck", "statusByte", "statusByteChannel", "getChannel", "eventDataLength", "dataBytesAmount", "eventData", "event", "MIDIMessage", "chunk", "dataSlice", "SpessaSynthCoreUtils", "consoleColors", "SpessaSynthInfo", "SpessaSynthWarn", "SpessaSynthGroupCollapsed", "SpessaSynthGroupEnd", "readBytesAsUintBigEndian", "readLittleEndian", "readBytesAsString", "readVariableLengthQuantity", "tr", "consoleColors", "SpessaSynthCoreUtils", "workletMessageType", "returnMessageType", "WORKLET_PROCESSOR_NAME", "workletKeyModifierMessageType", "WorkletSoundfontManagerMessageType", "SongChangeType", "SpessaSynthSequencerMessageType", "SpessaSynthSequencerReturnMessageType", "fillWithDefaults", "obj", "defObj", "key", "DEFAULT_SEQUENCER_OPTIONS", "MIDIData", "MIDISequenceData", "midi", "DUMMY_MIDI_DATA", "WorkletSpessaProcessor", "options", "opts", "postSyn", "t", "d", "startRenderingData", "snapshot", "SpessaSynthProcessor", "returnMessageType", "p", "n", "v", "SpessaSynthSequencer", "postSeq", "type", "data", "e", "m", "SpessaSynthSequencerReturnMessageType", "i", "a", "c", "l", "midiDataList", "s", "MIDIData", "SpessaSynthCoreUtils", "consoleColors", "seqOptions", "fillWithDefaults", "DEFAULT_SEQUENCER_OPTIONS", "message", "channel", "channelObject", "workletMessageType", "chan", "value", "seq", "messageData", "SpessaSynthSequencerMessageType", "songMap", "MIDI", "loop", "count", "SongChangeType", "sfManager", "WorkletSoundfontManagerMessageType", "keyMessageType", "man", "keyMessageData", "workletKeyModifierMessageType", "SynthesizerSnapshot", "SpessaSynthLogging", "inputs", "outputs", "out", "channelMap", "WORKLET_PROCESSOR_NAME"]
7
- }