@yam8d/m8-sdk 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +299 -233
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/types/parameterViews.d.ts +9 -0
package/dist/index.js
CHANGED
|
@@ -3279,11 +3279,11 @@ var bt = 20, xt = 700, St = 80, Ct = 4e3, wt = 120, Tt = (e, t) => {
|
|
|
3279
3279
|
notes: {
|
|
3280
3280
|
rows: "A row is recognised by 'match' conditions on the line text (x = column, text = exact text, regex = pattern on the value.width chars). The first matching row wins; its cells give the field columns.",
|
|
3281
3281
|
zones: "Views whose labels change (instrument parameters depend on the instrument type, modulation slots on the modulation type) use two label/value zones instead: the label text is read at labelX and the value at x. The label is then looked up in the vocabulary.",
|
|
3282
|
-
formats: "hex = 2 hex digits; hexOption = 2 hex digits followed by the option name ('00CHORUS'); hexPair = 'XX:YY'; decimal / decimalPair = base-10 numbers ('120', '150:45'); float = decimal with a fraction ('-05.00'); text = free text or option name; auto = detect from the text.",
|
|
3282
|
+
formats: "hex = 2 hex digits; hexOption = 2 hex digits followed by the option name ('00CHORUS'); hexPair = 'XX:YY' (or 'XX/YY'); decimal / decimalPair = base-10 numbers ('120', '150:45'); float = decimal with a fraction ('-05.00'); text = free text or option name; auto = detect from the text.",
|
|
3283
3283
|
unverified: "Positions are read off the manual's screenshots, not from a device capture. Instrument-type specific layouts other than the Wavsynth header/parameter grid (Sampler SAMPLE row, FM operators, Hypersynth chord, MIDI CC rows) are only reached through the generic label/value zones."
|
|
3284
3284
|
},
|
|
3285
|
-
views: /* @__PURE__ */ JSON.parse("{\"project\":{\"rows\":[{\"id\":\"tempo\",\"match\":[{\"x\":0,\"text\":\"TEMPO\"}],\"cells\":[{\"x\":13,\"width\":6,\"key\":\"tempo\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" BPM\",\"label\":\"Tempo (TEMPO)\",\"description\":\"Song speed in beats per minute. [EDIT] pressed rhythmically sets the tempo by tapping.\"}]},{\"id\":\"transpose\",\"match\":[{\"x\":0,\"text\":\"TRANSPOSE\"}],\"cells\":[{\"x\":13,\"width\":2,\"key\":\"transpose\",\"type\":\"transpose\",\"format\":\"hex\",\"label\":\"Project Transpose (TRANSPOSE)\",\"description\":\"Transposes the whole song in semitones (same as the TSP command). Only affects instruments with TRANSP. enabled; applied when [EDIT] is released.\"}]},{\"id\":\"groove\",\"match\":[{\"x\":0,\"text\":\"GROOVE\"}],\"cells\":[{\"x\":13,\"width\":14,\"key\":\"groove\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Default Groove (GROOVE)\",\"description\":\"Groove used when the song plays (number and name); applied when [EDIT] is released. See Groove View.\"}]},{\"id\":\"scale\",\"match\":[{\"x\":0,\"text\":\"SCALE\"}],\"cells\":[{\"x\":13,\"width\":16,\"key\":\"scale\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Default Scale (SCALE)\",\"description\":\"Scale (number, key and name) used when the song plays; applied when [EDIT] is released. See Scale View.\"}]},{\"id\":\"liveQuantize\",\"match\":[{\"x\":0,\"text\":\"LIVE QUANTIZ\"}],\"cells\":[{\"x\":13,\"width\":14,\"key\":\"liveQuantize\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Live Quantize (LIVE QUANTIZE)\",\"description\":\"How long a cued chain waits before starting when playing in live mode.\"}]},{\"id\":\"midi\",\"match\":[{\"x\":0,\"text\":\"MIDI\"},{\"x\":13,\"text\":\"SETTINGS\"}],\"cells\":[{\"x\":13,\"width\":8,\"key\":\"midiSettings\",\"type\":\"action\",\"format\":\"text\",\"label\":\"MIDI Settings\",\"description\":\"Open the MIDI Settings View.\"},{\"x\":22,\"width\":8,\"key\":\"midiMappings\",\"type\":\"action\",\"format\":\"text\",\"label\":\"MIDI Mappings\",\"description\":\"Open the MIDI Mappings View.\"}]},{\"id\":\"name\",\"match\":[{\"x\":0,\"text\":\"NAME\"}],\"cells\":[{\"x\":13,\"width\":12,\"key\":\"name\",\"type\":\"name\",\"format\":\"text\",\"label\":\"Song Name (NAME)\",\"description\":\"Name of the current song, entered before saving.\"}]},{\"id\":\"file\",\"match\":[{\"x\":0,\"text\":\"PROJECT\"},{\"x\":13,\"text\":\"LOAD\"}],\"cells\":[{\"x\":13,\"width\":4,\"key\":\"load\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Load Song\",\"description\":\"Load a song from the SD card.\"},{\"x\":18,\"width\":4,\"key\":\"save\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Save Song\",\"description\":\"Save the current song.\"},{\"x\":23,\"width\":3,\"key\":\"new\",\"type\":\"action\",\"format\":\"text\",\"label\":\"New Song\",\"description\":\"Create a new song.\"}]},{\"id\":\"export\",\"match\":[{\"x\":0,\"text\":\"EXPORT/SHARE\"}],\"cells\":[{\"x\":13,\"width\":6,\"key\":\"render\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Render\",\"description\":\"Open the Render View to render audio.\"},{\"x\":20,\"width\":6,\"key\":\"bundle\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Bundle\",\"description\":\"Bundle the song with the instruments and samples it uses.\"}]},{\"id\":\"clearUnused\",\"match\":[{\"x\":0,\"text\":\"CLEAR UNUSED\"}],\"cells\":[{\"x\":13,\"width\":7,\"key\":\"clearPhrases\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Clear Unused Phrases\",\"description\":\"Frees chains and phrases that are not used in the song.\"},{\"x\":21,\"width\":8,\"key\":\"clearInstTbl\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Clear Unused Instruments/Tables\",\"description\":\"Frees instruments, EQs and tables that are not used in the song.\"}]},{\"id\":\"instPool\",\"match\":[{\"x\":0,\"text\":\"INST. POOL\"}],\"cells\":[{\"x\":13,\"width\":15,\"key\":\"viewInstPool\",\"type\":\"action\",\"format\":\"text\",\"label\":\"View Instrument Pool\",\"description\":\"Go to the Instrument Pool View.\"}]},{\"id\":\"timeStats\",\"match\":[{\"x\":0,\"text\":\"TIME STATS\"}],\"cells\":[{\"x\":13,\"width\":15,\"key\":\"viewTimeStats\",\"type\":\"action\",\"format\":\"text\",\"label\":\"View Time Stats\",\"description\":\"Open the Time Stats View (time spent on the song).\"}]},{\"id\":\"system\",\"match\":[{\"x\":0,\"text\":\"SYSTEM\"},{\"x\":13,\"text\":\"SETTINGS\"}],\"cells\":[{\"x\":13,\"width\":8,\"key\":\"systemSettings\",\"type\":\"action\",\"format\":\"text\",\"label\":\"System Settings\",\"description\":\"Go to the System Settings View.\"},{\"x\":22,\"width\":9,\"key\":\"usbDrive\",\"type\":\"action\",\"format\":\"text\",\"label\":\"USB Drive\",\"description\":\"Puts the M8 in USB drive mode so SD card files can be transferred to a computer.\"}]}]},\"systemsettings\":{\"rows\":[{\"id\":\"backlight\",\"match\":[{\"x\":0,\"text\":\"BACKLIGHT\"}],\"cells\":[{\"x\":15,\"width\":2,\"key\":\"backlight\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Backlight (BACKLIGHT)\",\"description\":\"Backlight LED brightness of the display.\"}]},{\"id\":\"fontOptions\",\"match\":[{\"x\":0,\"text\":\"FONT OPTIONS\"}],\"cells\":[{\"x\":15,\"width\":15,\"key\":\"fontOptions\",\"type\":\"option\",\"format\":\"text\",\"label\":\"Font Options (FONT OPTIONS)\",\"description\":\"Font settings, including a large font mode for readability.\"}]},{\"id\":\"theme\",\"match\":[{\"x\":0,\"text\":\"THEME\"}],\"cells\":[{\"x\":15,\"width\":10,\"key\":\"editTheme\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Theme (EDIT THEME)\",\"description\":\"Open the Theme View.\"}]},{\"id\":\"notePreview\",\"match\":[{\"x\":0,\"text\":\"NOTE PREVIEW\"}],\"cells\":[{\"x\":15,\"width\":3,\"key\":\"notePreview\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Note Preview (NOTE PREVIEW)\",\"description\":\"Plays the note when editing notes in the phrase view.\"}]},{\"id\":\"recCountIn\",\"match\":[{\"x\":0,\"regex\":\"^REC\\\\.\\\\s?(COUNT IN|METRONOME)\\\\s*$\",\"width\":13}],\"cells\":[{\"x\":15,\"width\":6,\"key\":\"recCountIn\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Recording Count-in (REC. COUNT IN)\",\"description\":\"Number of phrases/measures of metronome count-in before recording audio in the Sample Editor or Selection to Sample.\"}]},{\"id\":\"metronomeVol\",\"match\":[{\"x\":0,\"text\":\"METRONOME VOL\"}],\"cells\":[{\"x\":15,\"width\":2,\"key\":\"metronomeVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Metronome Volume (METRONOME VOL)\",\"description\":\"Volume of the metronome sound (edit /System/Metronome.m8i to change the sound).\"}]},{\"id\":\"songTemplate\",\"match\":[{\"x\":0,\"text\":\"SONG TEMPLATE\"}],\"cells\":[{\"x\":15,\"width\":4,\"key\":\"songTemplateSave\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Song Template (SAVE)\",\"description\":\"Use the currently opened song as the template for new songs.\"},{\"x\":20,\"width\":5,\"key\":\"songTemplateClear\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Song Template (CLEAR)\",\"description\":\"Clear the song template.\"}]},{\"id\":\"usbAudioMode\",\"match\":[{\"x\":0,\"text\":\"USB AUDIO MODE\"}],\"cells\":[{\"x\":15,\"width\":14,\"key\":\"usbAudioMode\",\"type\":\"option\",\"format\":\"text\",\"label\":\"USB Audio Mode (USB AUDIO MODE)\",\"description\":\"USB output as stereo or multi-channel (multi-channel sends all 8 tracks and the effects individually, 12 stereo channels).\",\"options\":{\"STEREO OUT\":\"Stereo mix over USB.\"}}]},{\"id\":\"usbMainOut\",\"match\":[{\"x\":0,\"text\":\"USB MAIN OUT\"}],\"cells\":[{\"x\":15,\"width\":6,\"key\":\"usbMainOut\",\"type\":\"option\",\"format\":\"text\",\"label\":\"USB Main Out (USB MAIN OUT)\",\"description\":\"Routing behaviour of USB audio (see the USB audio routing options).\"}]},{\"id\":\"lineInGate\",\"match\":[{\"x\":0,\"text\":\"LINE-IN GATE\"}],\"cells\":[{\"x\":15,\"width\":6,\"key\":\"lineInGate\",\"type\":\"option\",\"format\":\"text\",\"label\":\"Line-in Gate (LINE-IN GATE)\",\"description\":\"Noise gate threshold for the line input, adjustable from -70 dB to -10 dB (OFF disables it).\"}]},{\"id\":\"splashScreen\",\"match\":[{\"x\":0,\"text\":\"SPLASH SCREEN\"}],\"cells\":[{\"x\":15,\"width\":3,\"key\":\"splashScreen\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Splash Screen (SPLASH SCREEN)\",\"description\":\"Show the M8 logo and play the start-up sound when turning on the device.\"}]},{\"id\":\"hpProtection\",\"match\":[{\"x\":0,\"text\":\"HP PROTECTION\"}],\"cells\":[{\"x\":15,\"width\":3,\"key\":\"hpProtection\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Headphone Protection (HP PROTECTION)\",\"description\":\"Limits the headphone output volume to F0 when a pack is unplugged and re-inserted.\"}]},{\"id\":\"keyDelayRep\",\"match\":[{\"x\":0,\"text\":\"KEY DELAY:REP\"}],\"cells\":[{\"x\":15,\"width\":7,\"key\":\"keyDelayRep\",\"type\":\"parameter\",\"format\":\"decimalPair\",\"unit\":\" ms\",\"parts\":[\"delay\",\"repeat\"],\"label\":\"Key Delay:Repeat (KEY DELAY:REP)\",\"description\":\"Key repeat timing in milliseconds: delay before a held key starts repeating, then the time between repeats.\"}]},{\"id\":\"battCharging\",\"match\":[{\"x\":0,\"regex\":\"^BATT\\\\.\\\\s?(CHARGING|STATUS)\\\\s*$\",\"width\":14}],\"cells\":[{\"x\":15,\"width\":14,\"key\":\"battCharging\",\"type\":\"option\",\"format\":\"text\",\"label\":\"Battery Charging (BATT. CHARGING / STATUS)\",\"description\":\"Whether the battery charges while the M8 is on and USB is connected (turn off to reduce power drawn from the host); also shows the current charging status.\"}]}]},\"effectsettings\":{\"sections\":[\"MODFX\",\"DELAY\",\"REVERB\"],\"rows\":[{\"id\":\"modfxType\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"MOD TYPE\"}],\"cells\":[{\"x\":21,\"width\":10,\"key\":\"modfxType\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"ModFX Type (MOD TYPE)\",\"description\":\"ModFX effect: Chorus, Phaser or Flanger (also sets the phase position).\",\"options\":{\"CHORUS\":\"Stereo chorus.\",\"PHASER\":\"Stereo phaser.\",\"FLANGER\":\"Stereo flanger.\"}}]},{\"id\":\"modfxInputEq\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"INPUT EQ\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"modfxInputEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Input EQ (INPUT EQ)\",\"description\":\"Open the EQ editor for this effect's input.\"}]},{\"id\":\"modfxDepthFreq\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"MOD DEPTH:FRQ\"}],\"cells\":[{\"x\":21,\"width\":5,\"key\":\"modfxDepthFreq\",\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"mod depth\",\"mod frequency\"],\"label\":\"ModFX Mod Depth:Frequency (MOD DEPTH:FRQ)\",\"description\":\"Amount of modulation in the stereo signal (first value) and speed of the modulation (second value).\"}]},{\"id\":\"modfxWidth\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"STEREO WIDTH\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"modfxWidth\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Stereo Width (STEREO WIDTH)\",\"description\":\"Stereo width: 00 is mono, FF is stereo.\"}]},{\"id\":\"modfxReverbSend\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"REVERB SEND\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"modfxReverbSend\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Reverb Send (REVERB SEND)\",\"description\":\"Amount of this effect sent to the reverb.\"}]},{\"id\":\"delayInputEq\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"INPUT EQ\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"delayInputEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Input EQ (INPUT EQ)\",\"description\":\"Open the EQ editor for this effect's input.\"}]},{\"id\":\"delayTime\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"TIME L:R\"}],\"cells\":[{\"x\":21,\"width\":5,\"key\":\"delayTime\",\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"left time\",\"right time\"],\"label\":\"Delay Time L:R (TIME L:R)\",\"description\":\"Delay time for the left and right channels: first digit in beats, second digit in fractions of a beat (40 is 4 beats).\"}]},{\"id\":\"delayFeedback\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"FEEDBACK\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"delayFeedback\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Feedback (FEEDBACK)\",\"description\":\"Amount of the delayed signal fed back into the delay.\"}]},{\"id\":\"delayWidth\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"STEREO WIDTH\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"delayWidth\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Stereo Width (STEREO WIDTH)\",\"description\":\"Stereo width: 00 is mono, FF is stereo.\"}]},{\"id\":\"delayReverbSend\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"REVERB SEND\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"delayReverbSend\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Reverb Send (REVERB SEND)\",\"description\":\"Amount of this effect sent to the reverb.\"}]},{\"id\":\"reverbInputEq\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"INPUT EQ\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"reverbInputEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Input EQ (INPUT EQ)\",\"description\":\"Open the EQ editor for this effect's input.\"}]},{\"id\":\"reverbRoomSize\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"ROOM SIZE\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"reverbRoomSize\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Room Size (ROOM SIZE)\",\"description\":\"Size of the reverb room.\"}]},{\"id\":\"reverbDecayShimmer\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"DECAY:SHIMMER\"}],\"cells\":[{\"x\":21,\"width\":5,\"key\":\"reverbDecayShimmer\",\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"decay\",\"shimmer\"],\"label\":\"Reverb Decay:Shimmer (DECAY:SHIMMER)\",\"description\":\"Reverb decay time (first value) and shimmer amount (second value).\"}]},{\"id\":\"reverbDepthFreq\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"MOD DEPTH:FRQ\"}],\"cells\":[{\"x\":21,\"width\":5,\"key\":\"reverbDepthFreq\",\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"mod depth\",\"mod frequency\"],\"label\":\"Reverb Mod Depth:Frequency (MOD DEPTH:FRQ)\",\"description\":\"Reverb modulation depth (first value) and frequency (second value).\"}]},{\"id\":\"reverbWidth\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"STEREO WIDTH\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"reverbWidth\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Stereo Width (STEREO WIDTH)\",\"description\":\"Stereo width: 00 is mono, FF is stereo.\"}]}]},\"mixer\":{\"rows\":[{\"id\":\"speaker\",\"match\":[{\"x\":0,\"text\":\"SPEAKER\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"speakerVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Speaker Volume (SPEAKER VOL)\",\"description\":\"Volume of the built-in speaker.\"}]},{\"id\":\"outputVol\",\"match\":[{\"x\":0,\"text\":\"OUTPUT VOL\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"outputVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Output Volume (OUTPUT VOL)\",\"description\":\"Volume of the audio output (headphones / line out).\"}]},{\"id\":\"tracks\",\"match\":[{\"x\":0,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2},{\"x\":21,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2}],\"cells\":[{\"x\":0,\"width\":2,\"key\":\"track1\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 1 Volume\",\"meta\":{\"trackIndex\":1},\"description\":\"Volume of track 1. Instrument volumes are applied on top; the track's send levels are set in the instruments.\"},{\"x\":3,\"width\":2,\"key\":\"track2\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 2 Volume\",\"meta\":{\"trackIndex\":2},\"description\":\"Volume of track 2.\"},{\"x\":6,\"width\":2,\"key\":\"track3\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 3 Volume\",\"meta\":{\"trackIndex\":3},\"description\":\"Volume of track 3.\"},{\"x\":9,\"width\":2,\"key\":\"track4\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 4 Volume\",\"meta\":{\"trackIndex\":4},\"description\":\"Volume of track 4.\"},{\"x\":12,\"width\":2,\"key\":\"track5\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 5 Volume\",\"meta\":{\"trackIndex\":5},\"description\":\"Volume of track 5.\"},{\"x\":15,\"width\":2,\"key\":\"track6\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 6 Volume\",\"meta\":{\"trackIndex\":6},\"description\":\"Volume of track 6.\"},{\"x\":18,\"width\":2,\"key\":\"track7\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 7 Volume\",\"meta\":{\"trackIndex\":7},\"description\":\"Volume of track 7.\"},{\"x\":21,\"width\":2,\"key\":\"track8\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 8 Volume\",\"meta\":{\"trackIndex\":8},\"description\":\"Volume of track 8.\"}]},{\"id\":\"eq\",\"match\":[{\"x\":27,\"text\":\"EQ\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"mixEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Main Mix EQ (EQ)\",\"description\":\"Open the main mix EQ editor ([EDIT] or [SHIFT]+[RIGHT]).\"}]},{\"id\":\"levels\",\"match\":[{\"x\":0,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2},{\"x\":3,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2},{\"x\":6,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2},{\"x\":12,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2}],\"cells\":[{\"x\":0,\"width\":2,\"key\":\"modfxVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"ModFX Volume (MX)\",\"description\":\"Output level of the ModFX send effect.\"},{\"x\":3,\"width\":2,\"key\":\"delayVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Delay Volume (DE)\",\"description\":\"Output level of the delay send effect.\"},{\"x\":6,\"width\":2,\"key\":\"reverbVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Reverb Volume (RE)\",\"description\":\"Output level of the reverb send effect.\"},{\"x\":12,\"width\":2,\"key\":\"inputVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input Volume (INPUT)\",\"description\":\"Volume of the analog input for monitoring. In dual-mono mode this is the left channel.\"},{\"x\":15,\"width\":2,\"key\":\"inputVol2\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input Volume, 2nd channel\",\"description\":\"Enables dual-mono input mode when set (right channel volume); clear with [EDIT]+[OPTION] to disable.\"},{\"x\":18,\"width\":2,\"key\":\"usbVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"USB Input Volume (USB)\",\"description\":\"Volume of anything the USB host computer sends to the M8.\"},{\"x\":27,\"width\":2,\"key\":\"mainVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Main Volume (MIX)\",\"description\":\"Main song volume, applied after the limiter, DJ filter and OTT. [EDIT] or [SHIFT]+[RIGHT] opens the Mix Scope.\"}]},{\"id\":\"limiter\",\"match\":[{\"x\":0,\"text\":\"MX\"},{\"x\":3,\"text\":\"DE\"},{\"x\":6,\"text\":\"RE\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"limiter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter (LIM)\",\"description\":\"Main mix limiter amount; the limiter is engaged when the value is above 00. [EDIT] or [SHIFT]+[RIGHT] opens the Limiter Scope.\"}]},{\"id\":\"sendModfx\",\"match\":[{\"x\":9,\"text\":\"MX\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"inputModfx\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input ModFX Send (INPUT MX)\",\"description\":\"How much of the analog input goes to the ModFX effect.\"},{\"x\":18,\"width\":2,\"key\":\"usbModfx\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"USB Input ModFX Send (USB MX)\",\"description\":\"How much of the USB input goes to the ModFX effect.\"},{\"x\":27,\"width\":2,\"key\":\"djFilter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"DJ Filter (DJF)\",\"description\":\"DJ filter cutoff: 80 is off, below 80 low-pass (or band-stop), above 80 high-pass. Mode and options are in the Scope View.\"}]},{\"id\":\"sendDelay\",\"match\":[{\"x\":9,\"text\":\"DE\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"inputDelay\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input Delay Send (INPUT DE)\",\"description\":\"How much of the analog input goes to the delay effect.\"},{\"x\":18,\"width\":2,\"key\":\"usbDelay\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"USB Input Delay Send (USB DE)\",\"description\":\"How much of the USB input goes to the delay effect.\"},{\"x\":27,\"width\":2,\"key\":\"ott\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"OTT (OTT)\",\"description\":\"Over The Top multi-band compression mixed in parallel: 00 to 80 mixes it in; from 80 and above the main mix is faded out.\"}]},{\"id\":\"sendReverb\",\"match\":[{\"x\":9,\"text\":\"RE\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"inputReverb\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input Reverb Send (INPUT RE)\",\"description\":\"How much of the analog input goes to the reverb effect.\"},{\"x\":18,\"width\":2,\"key\":\"usbReverb\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"USB Input Reverb Send (USB RE)\",\"description\":\"How much of the USB input goes to the reverb effect.\"}]}]},\"mixeq\":{\"rows\":[{\"id\":\"gain\",\"match\":[{\"x\":0,\"text\":\"GAIN\"}],\"cells\":[{\"x\":5,\"width\":6,\"key\":\"lowGain\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" dB\",\"label\":\"LOW Gain\",\"description\":\"Boost (positive) or cut (negative) applied by the LOW band, in decibels.\"},{\"x\":16,\"width\":6,\"key\":\"midGain\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" dB\",\"label\":\"MID Gain\",\"description\":\"Boost (positive) or cut (negative) applied by the MID band, in decibels.\"},{\"x\":27,\"width\":6,\"key\":\"highGain\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" dB\",\"label\":\"HIGH Gain\",\"description\":\"Boost (positive) or cut (negative) applied by the HIGH band, in decibels.\"}]},{\"id\":\"freq\",\"match\":[{\"x\":0,\"text\":\"FREQ\"}],\"cells\":[{\"x\":6,\"width\":5,\"key\":\"lowFreq\",\"type\":\"parameter\",\"format\":\"decimal\",\"unit\":\" Hz\",\"label\":\"LOW Frequency\",\"description\":\"Centre (or corner) frequency of the LOW band.\"},{\"x\":17,\"width\":5,\"key\":\"midFreq\",\"type\":\"parameter\",\"format\":\"decimal\",\"unit\":\" Hz\",\"label\":\"MID Frequency\",\"description\":\"Centre (or corner) frequency of the MID band.\"},{\"x\":28,\"width\":5,\"key\":\"highFreq\",\"type\":\"parameter\",\"format\":\"decimal\",\"unit\":\" Hz\",\"label\":\"HIGH Frequency\",\"description\":\"Centre (or corner) frequency of the HIGH band.\"}]},{\"id\":\"q\",\"match\":[{\"x\":0,\"text\":\"Q\"},{\"x\":1,\"regex\":\"^\\\\s?$\",\"width\":1}],\"cells\":[{\"x\":6,\"width\":3,\"key\":\"lowQ\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"LOW Q\",\"description\":\"Quality factor (bandwidth) of the LOW band: higher values narrow it.\"},{\"x\":17,\"width\":3,\"key\":\"midQ\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"MID Q\",\"description\":\"Quality factor (bandwidth) of the MID band: higher values narrow it.\"},{\"x\":28,\"width\":3,\"key\":\"highQ\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"HIGH Q\",\"description\":\"Quality factor (bandwidth) of the HIGH band: higher values narrow it.\"}]},{\"id\":\"type\",\"match\":[{\"x\":0,\"text\":\"TYPE\"}],\"cells\":[{\"x\":6,\"width\":9,\"key\":\"lowType\",\"type\":\"option\",\"format\":\"text\",\"label\":\"LOW Type\",\"description\":\"Filter shape of the LOW band.\",\"options\":{\"LOWCUT\":\"Removes frequencies below the cutoff.\",\"LOWSHELF\":\"Boosts or cuts frequencies below the shelf frequency.\",\"BELL\":\"Peaking filter: boosts or cuts around the centre frequency.\",\"BANDPASS\":\"Passes frequencies around the centre frequency, attenuating both sides.\",\"HI.SHELF\":\"Boosts or cuts frequencies above the shelf frequency.\",\"HI.CUT\":\"Attenuates or removes frequencies above the cutoff.\",\"ALLPASS\":\"Passes all frequencies at equal gain while shifting their phase.\"}},{\"x\":17,\"width\":9,\"key\":\"midType\",\"type\":\"option\",\"format\":\"text\",\"label\":\"MID Type\",\"description\":\"Filter shape of the MID band.\",\"options\":{\"LOWCUT\":\"Removes frequencies below the cutoff.\",\"LOWSHELF\":\"Boosts or cuts frequencies below the shelf frequency.\",\"BELL\":\"Peaking filter: boosts or cuts around the centre frequency.\",\"BANDPASS\":\"Passes frequencies around the centre frequency, attenuating both sides.\",\"HI.SHELF\":\"Boosts or cuts frequencies above the shelf frequency.\",\"HI.CUT\":\"Attenuates or removes frequencies above the cutoff.\",\"ALLPASS\":\"Passes all frequencies at equal gain while shifting their phase.\"}},{\"x\":28,\"width\":9,\"key\":\"highType\",\"type\":\"option\",\"format\":\"text\",\"label\":\"HIGH Type\",\"description\":\"Filter shape of the HIGH band.\",\"options\":{\"LOWCUT\":\"Removes frequencies below the cutoff.\",\"LOWSHELF\":\"Boosts or cuts frequencies below the shelf frequency.\",\"BELL\":\"Peaking filter: boosts or cuts around the centre frequency.\",\"BANDPASS\":\"Passes frequencies around the centre frequency, attenuating both sides.\",\"HI.SHELF\":\"Boosts or cuts frequencies above the shelf frequency.\",\"HI.CUT\":\"Attenuates or removes frequencies above the cutoff.\",\"ALLPASS\":\"Passes all frequencies at equal gain while shifting their phase.\"}}]},{\"id\":\"mode\",\"match\":[{\"x\":0,\"text\":\"MODE\"}],\"cells\":[{\"x\":6,\"width\":6,\"key\":\"lowMode\",\"type\":\"option\",\"format\":\"text\",\"label\":\"LOW Mode\",\"description\":\"How the LOW band is applied to the stereo signal.\",\"options\":{\"STEREO\":\"Processes left and right identically.\",\"MID\":\"Affects only the mid (centre) information.\",\"SIDE\":\"Affects only the side information (difference between left and right).\",\"LEFT\":\"Affects only the left channel.\",\"RIGHT\":\"Affects only the right channel.\"}},{\"x\":17,\"width\":6,\"key\":\"midMode\",\"type\":\"option\",\"format\":\"text\",\"label\":\"MID Mode\",\"description\":\"How the MID band is applied to the stereo signal.\",\"options\":{\"STEREO\":\"Processes left and right identically.\",\"MID\":\"Affects only the mid (centre) information.\",\"SIDE\":\"Affects only the side information (difference between left and right).\",\"LEFT\":\"Affects only the left channel.\",\"RIGHT\":\"Affects only the right channel.\"}},{\"x\":28,\"width\":6,\"key\":\"highMode\",\"type\":\"option\",\"format\":\"text\",\"label\":\"HIGH Mode\",\"description\":\"How the HIGH band is applied to the stereo signal.\",\"options\":{\"STEREO\":\"Processes left and right identically.\",\"MID\":\"Affects only the mid (centre) information.\",\"SIDE\":\"Affects only the side information (difference between left and right).\",\"LEFT\":\"Affects only the left channel.\",\"RIGHT\":\"Affects only the right channel.\"}}]}]},\"modfxeq\":{\"extends\":\"mixeq\"},\"delayeq\":{\"extends\":\"mixeq\"},\"reverbeq\":{\"extends\":\"mixeq\"},\"mixscope\":{\"rows\":[{\"id\":\"limiterAtkRel\",\"match\":[{\"x\":9,\"text\":\"ATK\"},{\"x\":16,\"text\":\"REL\"},{\"x\":23,\"text\":\"LIM\"}],\"cells\":[{\"x\":13,\"width\":2,\"key\":\"attack\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter Attack (ATK)\",\"description\":\"Limiter attack time from 0 to 100 ms (see the on-screen help text for the conversion to milliseconds).\"},{\"x\":20,\"width\":2,\"key\":\"release\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter Release (REL)\",\"description\":\"Limiter release time from 4 to 1000 ms; 00 activates AUTO mode (100-900 ms depending on the compression amount).\"},{\"x\":27,\"width\":2,\"key\":\"limiter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter (LIM)\",\"description\":\"Limiter amount.\"}]},{\"id\":\"zoomPeak\",\"match\":[{\"x\":0,\"text\":\"ZOOM\"}],\"cells\":[{\"x\":5,\"width\":5,\"key\":\"zoom\",\"type\":\"parameter\",\"format\":\"text\",\"label\":\"Zoom (ZOOM)\",\"description\":\"Lower limit of the scope histogram, in decibels.\"},{\"x\":20,\"width\":6,\"key\":\"peak\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" dB\",\"label\":\"Peak (PEAK)\",\"description\":\"Current peak level of the main mix in dB. Resets when MIX or LIM change; clear it with [OPT]+[EDIT].\"}]},{\"id\":\"eq\",\"match\":[{\"x\":27,\"text\":\"EQ\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"mixEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Main Mix EQ (EQ)\",\"description\":\"Open the main mix EQ editor.\"}]},{\"id\":\"softClip\",\"match\":[{\"x\":9,\"text\":\"SOFT CLIP\"}],\"cells\":[{\"x\":19,\"width\":3,\"key\":\"softClip\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Soft Clip (SOFT CLIP)\",\"description\":\"Gentle saturation after the limiter to prevent harsh clipping; raise MIX to exaggerate it.\"},{\"x\":27,\"width\":2,\"key\":\"mainVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Main Volume (MIX)\",\"description\":\"Main mix / song volume, applied after the limiter stage.\"}]},{\"id\":\"mix\",\"match\":[{\"x\":23,\"text\":\"MIX\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"mainVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Main Volume (MIX)\",\"description\":\"Main mix / song volume, applied after the limiter stage.\"}]},{\"id\":\"lim\",\"match\":[{\"x\":23,\"text\":\"LIM\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"limiter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter (LIM)\",\"description\":\"Limiter amount.\"}]},{\"id\":\"djf\",\"match\":[{\"x\":23,\"text\":\"DJF\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"djFilter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"DJ Filter (DJF)\",\"description\":\"DJ filter cutoff: 80 is off, 00-80 low-pass, 80-FF high-pass (mode set with TYPE).\"}]},{\"id\":\"ott\",\"match\":[{\"x\":23,\"text\":\"OTT\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"ott\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"OTT (OTT)\",\"description\":\"OTT mix amount; from 80 and above the main mix volume is faded out.\"}]}],\"zones\":[{\"id\":\"right\",\"labelX\":23,\"labelWidth\":4,\"x\":27,\"width\":6}],\"vocabulary\":{\"ATK\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter Attack (ATK)\",\"description\":\"Limiter attack time from 0 to 100 ms (see the on-screen help text for the conversion).\"},\"REL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter Release (REL)\",\"description\":\"Limiter release time from 4 to 1000 ms; 00 activates AUTO mode (100-900 ms depending on the compression amount).\"},\"TYPE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"DJ Filter Type (TYPE)\",\"description\":\"DJ filter type: low-pass/high-pass, low-pass/band-stop or band-stop/high-pass.\"},\"RES\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"DJ Filter Resonance (RES)\",\"description\":\"Resonance of the DJ filter.\"},\"TIME\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"OTT Time (TIME)\",\"description\":\"OTT compressor envelope time as a percentage from 10% to 1000%.\"},\"COLOR\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"OTT Color (COLOR)\",\"description\":\"OTT compressor bands and low/high gains: above 80 shifts toward treble, below 80 toward bass.\"}}},\"limiterscope\":{\"extends\":\"mixscope\"},\"inst\":{\"rows\":[{\"id\":\"type\",\"match\":[{\"x\":0,\"text\":\"TYPE\"}],\"cells\":[{\"x\":8,\"width\":13,\"key\":\"instrumentType\",\"type\":\"instrumentType\",\"format\":\"text\",\"label\":\"Instrument Type (TYPE)\",\"description\":\"Kind of instrument in this slot: Wavsynth, Macrosynth, Sampler, FM Synth, Hypersynth, External Instrument, MIDI Out (or NONE for an unused slot). Changing it changes the parameters below.\"},{\"x\":22,\"width\":4,\"key\":\"load\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Load Preset (LOAD)\",\"description\":\"Load an instrument preset from the SD card.\"},{\"x\":27,\"width\":4,\"key\":\"save\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Save Preset (SAVE)\",\"description\":\"Save this instrument as a preset on the SD card.\"}]},{\"id\":\"name\",\"match\":[{\"x\":0,\"text\":\"NAME\"}],\"cells\":[{\"x\":8,\"width\":12,\"key\":\"name\",\"type\":\"name\",\"format\":\"text\",\"label\":\"Instrument Name (NAME)\",\"description\":\"Name of the instrument: helps keep the song organised when browsing, saving or bundling instruments.\"}]},{\"id\":\"transp\",\"match\":[{\"x\":0,\"text\":\"TRANSP.\"}],\"cells\":[{\"x\":8,\"width\":3,\"key\":\"transpose\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Transpose Enabled (TRANSP.)\",\"description\":\"Enable or disable note transposition from scales, chain transpose columns and the project transpose for this instrument (turn off for percussive or effect instruments).\"},{\"x\":21,\"width\":2,\"key\":\"tableTic\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Table Tick (TBL. TIC)\",\"description\":\"Default speed at which this instrument's table advances: 01 is one tick per step, 02 two ticks per step. Can be overridden by the TIC command.\"},{\"x\":29,\"width\":2,\"key\":\"eq\",\"type\":\"eqSlot\",\"format\":\"hex\",\"label\":\"EQ Slot (EQ)\",\"description\":\"EQ bank assigned to this instrument (-- for none). [EDIT] or [SHIFT]+[RIGHT] opens the EQ editor.\"}]}],\"zones\":[{\"id\":\"left\",\"labelX\":0,\"labelWidth\":8,\"x\":8,\"width\":20},{\"id\":\"right\",\"labelX\":18,\"labelWidth\":4,\"x\":22,\"width\":11}],\"vocabularyFrom\":\"instrumentTypes\"},\"instmods\":{\"slotLabel\":\"MOD\\\\d\",\"zones\":[{\"id\":\"left\",\"labelX\":0,\"labelWidth\":4,\"x\":5,\"width\":10},{\"id\":\"right\",\"labelX\":16,\"labelWidth\":4,\"x\":21,\"width\":10}],\"vocabulary\":{\"MOD#\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Modulator Type\",\"description\":\"Type of this modulation slot: AHD envelope, ADSR envelope, DRUM envelope, LFO, TRIG envelope or TRACKING. Slots can modulate their neighbour (Mod 1 affects Mod 2, 2→3, 3→4, 4→1).\",\"options\":{\"AHD ENV\":\"Attack Hold Decay envelope based on tempo.\",\"ADSR ENV\":\"Traditional Attack Decay Sustain Release envelope.\",\"DRUM ENV\":\"Sharp peak and swelling hold envelope for percussive elements.\",\"LFO\":\"Tempo-synced low frequency oscillator.\",\"TRIG ENV\":\"AHD envelope triggered by another playing track or instrument.\",\"TRACKING\":\"Modulates an instrument parameter from notes or velocities.\",\"OFF\":\"Slot unused.\"}},\"DEST\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Destination (DEST)\",\"description\":\"Instrument parameter this modulator controls. MOD AMT, MOD RATE or MOD BOTH modulate the neighbouring modulator's amount, rate or both.\"},\"SRC\":{\"type\":\"parameter\",\"format\":\"hexOption\",\"label\":\"Source (SRC)\",\"description\":\"Modulation source. Trig envelope: an instrument number (00-7F) or a whole track (80-87 = tracks 1-8). Tracking: NOTE, VELOCITY or VELOCITY TAKEOVER (velocity no longer affects instrument volume).\"},\"AMT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Amount (AMT)\",\"description\":\"How strongly the modulator is applied to the destination.\"},\"ATK\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Attack (ATK)\",\"description\":\"Time to reach the amount (in ticks, relative to tempo).\"},\"HOLD\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Hold (HOLD)\",\"description\":\"Time to wait after the attack before decaying (in ticks).\"},\"DEC\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Decay (DEC)\",\"description\":\"Time to fall back (AHD/Drum: to zero; ADSR: to the sustain level), in ticks.\"},\"SUS\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Sustain (SUS)\",\"description\":\"Level held while the note is playing (ADSR).\"},\"REL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Release (REL)\",\"description\":\"Time to fall back to zero after the note is released (ADSR); needs an OFF note or FX command.\"},\"PEAK\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Peak (PEAK)\",\"description\":\"Shape of the initial transient (drum envelope); modifies the duck amount and peak time.\"},\"BODY\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Body (BODY)\",\"description\":\"Time to hold the modulation before decaying (drum envelope).\"},\"OSC\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"LFO Shape (OSC)\",\"description\":\"LFO shape: triangle, sine, ramp down/up, exponential down/up, square down/up, random, drunk. The 'T' variants run in ticks (much faster).\",\"options\":{\"TRI\":\"Triangle.\",\"SIN\":\"Sine.\",\"RAMP DN\":\"Ramp down.\",\"RAMP UP\":\"Ramp up.\",\"EXP DN\":\"Exponential down.\",\"EXP UP\":\"Exponential up.\",\"SQU DN\":\"Square down.\",\"SQU UP\":\"Square up.\",\"RANDOM\":\"Random values.\",\"DRUNK\":\"Random walk.\"}},\"TRIG\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"LFO Trigger (TRIG)\",\"description\":\"How the LFO reacts when the instrument triggers and when the shape ends.\",\"options\":{\"FREE\":\"Loop the shape and don't reset on new notes.\",\"RETRIG\":\"Loop the shape and reset on each instrument trigger.\",\"HOLD\":\"Hold the last value of the shape.\",\"ONCE\":\"Play the shape once and reset to the start value.\"}},\"FREQ\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"LFO Frequency (FREQ)\",\"description\":\"Rate of the LFO in steps (16th notes), or in ticks for the 'T' shapes.\"},\"LVAL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Low Value (LVAL)\",\"description\":\"Lowest value of the source range scaled to the destination (tracking). Can be higher than HVAL to invert the range.\"},\"HVAL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"High Value (HVAL)\",\"description\":\"Highest value of the source range scaled to the destination (tracking).\"}}},\"scale\":{\"notes\":\"Only the rows below the 12 interval rows; the intervals themselves are grid columns in m8-view-context.json.\",\"rows\":[{\"id\":\"key\",\"match\":[{\"x\":0,\"text\":\"KEY\"}],\"cells\":[{\"x\":6,\"width\":2,\"key\":\"key\",\"type\":\"option\",\"format\":\"text\",\"label\":\"Key (KEY)\",\"description\":\"Global key: the root note of the default scale (can be overridden per track with SCA / SCG).\"}]},{\"id\":\"tune\",\"match\":[{\"x\":0,\"text\":\"TUNE\"}],\"cells\":[{\"x\":6,\"width\":6,\"key\":\"tune\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" Hz\",\"label\":\"Tuning (TUNE)\",\"description\":\"Reference pitch of A4 in Hz (440.00 is standard).\"}]},{\"id\":\"name\",\"match\":[{\"x\":0,\"text\":\"NAME\"}],\"cells\":[{\"x\":6,\"width\":16,\"key\":\"name\",\"type\":\"name\",\"format\":\"text\",\"label\":\"Scale Name (NAME)\",\"description\":\"Name of this scale (up to 16 characters); 92 factory scales load from /Scales/Factory.\"}]},{\"id\":\"file\",\"match\":[{\"x\":6,\"text\":\"LOAD\"},{\"x\":11,\"text\":\"SAVE\"}],\"cells\":[{\"x\":6,\"width\":4,\"key\":\"load\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Load Scale (LOAD)\",\"description\":\"Load a scale from the SD card.\"},{\"x\":11,\"width\":4,\"key\":\"save\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Save Scale (SAVE)\",\"description\":\"Save this scale to the SD card.\"}]}]},\"loadinstrument\":{\"kind\":\"browser\",\"browserFor\":\"instrument preset\"},\"selectsavedirectory\":{\"kind\":\"browser\",\"browserFor\":\"save location\"},\"createdirectory\":{\"kind\":\"text\",\"fieldLabel\":\"Directory Name\",\"description\":\"Name of the directory to create on the SD card.\"}}"),
|
|
3286
|
-
instrumentTypes: /* @__PURE__ */ JSON.parse("{\"common\":{\"name\":\"Common\",\"description\":\"Parameters shared by most instrument types.\",\"params\":{\"FILTER\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Filter Type (FILTER)\",\"description\":\"Multi-mode filter type: low-pass, high-pass, band-pass, band-stop, LP>HP (low-pass with RES controlling a 1-pole high-pass), ZDF low-pass, ZDF high-pass.\"},\"CUTOFF\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Filter Cutoff (CUTOFF)\",\"description\":\"Filter cutoff frequency.\"},\"RES\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Filter Resonance (RES)\",\"description\":\"Filter resonance amount.\"},\"AMP\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Amplification (AMP)\",\"description\":\"Amplifies the signal; values above the maximum level are handled according to LIM.\"},\"LIM\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Limit Mode (LIM)\",\"description\":\"Limit / clipping behaviour of the amplified signal.\",\"options\":{\"CLIP\":\"Values above the maximum level are clipped.\",\"SIN\":\"The waveform is fed through a sine function.\",\"FOLD\":\"Values above the maximum level are folded back into themselves.\",\"WRAP\":\"Values above the maximum level are wrapped vertically.\",\"POST\":\"Amplification applied with hard-clipping after the filter stage.\",\"POST:AD\":\"Post filter amplification with soft-clipping.\",\"POST:W1\":\"Post filter folding distortion.\",\"POST:W2\":\"Post filter folding distortion.\",\"POST:W3\":\"Post filter folding distortion.\"}},\"PAN\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Pan (PAN)\",\"description\":\"Stereo position of the instrument (80 is centre).\"},\"DRY\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Dry Volume (DRY)\",\"description\":\"Dry volume sent to the mixer channel.\"},\"MFX\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"ModFX Send (MFX)\",\"description\":\"ModFX send effect volume.\"},\"DEL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Delay Send (DEL)\",\"description\":\"Delay send effect volume.\"},\"REV\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Reverb Send (REV)\",\"description\":\"Reverb send effect volume.\"}}},\"wavsynth\":{\"name\":\"Wavsynth\",\"description\":\"Wave table synthesizer and noise generator: an 8-bit sample buffer generated in real time from one of 9 basic shapes (repeated, skewed, mirrored, filtered, overdriven) or one of 61 built-in wave tables of 64 waveforms each.\",\"params\":{\"SHAPE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Shape (SHAPE)\",\"description\":\"Base waveform: PULSE 12% to 75%, SAW, TRIANGLE, SINE, NOISE PITCHED, NOISE, or WT wave tables. For PWM set PULSE 50% and adjust MIRROR (smoothness set by SIZE).\"},\"SIZE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Size (SIZE)\",\"description\":\"Horizontal size of the waveform (number of samples).\"},\"MULT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Multiply (MULT)\",\"description\":\"Multiplies the waveform by adding repeats of the shape; can sound like hard sync.\"},\"WARP\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Warp (WARP)\",\"description\":\"Pushes the shape to one side of the wave table.\"},\"SCAN\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Scan / Mirror (SCAN)\",\"description\":\"Shapes 0-8: mirrors the waveform at the given position (0-200%). Wave tables: scans through the 64 waveforms.\"},\"FILTER\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Filter Type (FILTER)\",\"description\":\"Multi-mode filter type, plus 4 modes that apply the filter into the waveform: WAV LP, WAV HP, WAV BP, WAV BS.\"}}},\"macrosynth\":{\"name\":\"Macrosynth\",\"description\":\"44 engines ('shapes') from basic analog to 2-op FM, physical modelling and percussion; TIMBRE and COLOR change meaning per shape.\",\"params\":{\"SHAPE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Shape (SHAPE)\",\"description\":\"One of the 44 Macrosynth engines (see the Macrosynth Models appendix).\"},\"TIMBRE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Timbre (TIMBRE)\",\"description\":\"First parameter of the selected shape.\"},\"COLOR\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Color (COLOR)\",\"description\":\"Second parameter of the selected shape.\"},\"DEGRADE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Degrade (DEGRADE)\",\"description\":\"Sample rate reduction effect.\"},\"REDUX\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Redux (REDUX)\",\"description\":\"Bit rate reduction effect.\"}}},\"sampler\":{\"name\":\"Sampler\",\"description\":\"Sample player, editor and recorder for 1 or 2 channel PCM .wav files.\",\"params\":{\"SAMPLE\":{\"type\":\"name\",\"format\":\"text\",\"label\":\"Sample (SAMPLE)\",\"description\":\"The loaded sample; use LOAD to browse for one, REC. to record or EDIT to open the Sample Editor.\"},\"SLICE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Slice (SLICE)\",\"description\":\"Slices the sample into equal sections, mapped from the lowest octave (C-1); 01 FILE uses the markers stored in the file.\"},\"PLAY\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Play Mode (PLAY)\",\"description\":\"Play direction and loop mode.\",\"options\":{\"FWD\":\"Forward, no loop.\",\"REV\":\"Reverse, no loop.\",\"FWDLOOP\":\"Looping forward.\",\"REVLOOP\":\"Looping reverse.\",\"FWD PP\":\"Ping-pong looping, forward first.\",\"REV PP\":\"Ping-pong looping, reverse first.\",\"OSC\":\"Oscillator mode: ignores the start position and doesn't restart on retrigger.\",\"OSC REV\":\"Oscillator mode, reverse.\",\"OSC PP\":\"Oscillator mode, ping-pong.\",\"REPITCH\":\"Pitches the sample from the song tempo (adjust with STEPS/BPM).\"}},\"START\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Start (START)\",\"description\":\"Sample start position (ignored in OSC play modes).\"},\"LOOP ST.\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Loop Start (LOOP ST.)\",\"description\":\"Where the sample loops back to when it reaches the end in a looping play mode.\"},\"LEN\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Length (LEN)\",\"description\":\"Sample length.\"},\"DETUNE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Detune (DETUNE)\",\"description\":\"Detune with 80 as the centre frequency: first digit steps semitones, second digit 1/16 semitone.\"},\"DEGRADE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Degrade (DEGRADE)\",\"description\":\"Sample rate reduction; any value above 00 disables sample interpolation.\"}}},\"fmsynth\":{\"name\":\"FM Synth\",\"description\":\"Four-operator, 12-algorithm FM synthesizer. Each operator has a base shape, ratio, level, feedback and two modulation slots.\",\"params\":{\"ALGO\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Algorithm (ALGO)\",\"description\":\"One of 12 algorithms (oscillator routing); the last one is additive mode.\"},\"A\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Operator A (A)\",\"description\":\"Operator letter with optional shape (SIN, SW2-SW6, SAW, SQU, PUL, IMP, TRI, NOISE, then wave tables).\"},\"B\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Operator B (B)\",\"description\":\"Operator letter with optional shape.\"},\"C\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Operator C (C)\",\"description\":\"Operator letter with optional shape.\"},\"D\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Operator D (D)\",\"description\":\"Operator letter with optional shape.\"},\"RATIO\":{\"type\":\"parameter\",\"format\":\"float\",\"label\":\"Ratio (RATIO)\",\"description\":\"Operator frequency ratio relative to the played note (2.00 is an octave up, 0.50 an octave down).\"},\"LEV/FB\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Level / Feedback (LEV/FB)\",\"description\":\"Operator volume and feedback.\"},\"MOD\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Modulation Slot (MOD)\",\"description\":\"Assigns one of MOD1-MOD4 to control a destination on the operator.\"},\"LEV\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Level Mod (LEV)\",\"description\":\"Controls the level from 00 to the currently set level.\"},\"RAT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Ratio Mod (RAT)\",\"description\":\"Adds 0.00 to +16.00 to the current ratio.\"},\"PIT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Pitch Mod (PIT)\",\"description\":\"Adds to the note pitch, in semitones, for the operator.\"},\"FBK\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Feedback Mod (FBK)\",\"description\":\"Controls feedback from 00 to the currently set feedback.\"},\"MOD#\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Modulation Source\",\"description\":\"Modulation source value freely assigned to operators through the MOD slots.\"}}},\"hypersynth\":{\"name\":\"Hypersynth\",\"description\":\"Six-note saw wave chord synthesizer with 16 chord banks of up to 6 intervals, detune (swarm), stereo width and a square sub-oscillator.\",\"params\":{\"SCALE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Scale (SCALE)\",\"description\":\"One of the song's scales, or 00 to use the song/track scale settings.\"},\"CHORD\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Chord (CHORD)\",\"description\":\"Chord bank and its intervals (copy with [SHIFT]+[OPTION], paste with [SHIFT]+[EDIT]).\"},\"SHIFT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Shift (SHIFT)\",\"description\":\"Cross-fades volume between the first 3 intervals and the second 3.\"},\"SWARM\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Swarm (SWARM)\",\"description\":\"Detunes the oscillators relative to their interval.\"},\"WIDTH\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Stereo Width (WIDTH)\",\"description\":\"Stereo width of the oscillators, from mono 00 to full stereo FF.\"},\"SUBOSC\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Sub Oscillator (SUBOSC)\",\"description\":\"Mixes in a sub-oscillator 2 octaves below the root (below 80) or 1 octave below (above 80).\"}}},\"external\":{\"name\":\"External Instrument\",\"description\":\"Hybrid MIDI output and audio input device: notes and MIDI FX are sent to the chosen port and channel, audio returns through its filter and amp stage.\",\"params\":{\"INPUT\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Audio Input (INPUT)\",\"description\":\"Audio input: line-in (stereo, left, right), USB (stereo, left, right), or line-in and USB.\"},\"PORT\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"MIDI Port (PORT)\",\"description\":\"MIDI output port: MIDI and USB, MIDI only, USB only, or Internal (track MIDI input / global MIDI CCs from the MIDI Settings View).\"},\"CHANNEL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"MIDI Channel (CHANNEL)\",\"description\":\"MIDI channel, 1 to 16.\"},\"BANK:PG\":{\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"bank\",\"program\"],\"label\":\"Bank / Program (BANK:PG)\",\"description\":\"Optional MIDI bank select and program change (program change can also be sent as an FX command).\"},\"CC#\":{\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"CC number\",\"value\"],\"label\":\"Custom CC (CC:VAL)\",\"description\":\"A custom MIDI CC number with an optional default value, sent with the note-on after program change messages.\"}}},\"midiout\":{\"name\":\"MIDI Out\",\"description\":\"Controls external devices over USB MIDI or the TRS (type A) MIDI output.\",\"params\":{\"PORT\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"MIDI Port (PORT)\",\"description\":\"MIDI output port: MIDI and USB, MIDI only, USB only, or Internal (track MIDI input / global MIDI CCs from the MIDI Settings View).\"},\"CHANNEL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"MIDI Channel (CHANNEL)\",\"description\":\"MIDI channel, 1 to 16.\"},\"BANK:PG\":{\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"bank\",\"program\"],\"label\":\"Bank / Program (BANK:PG)\",\"description\":\"Optional MIDI bank select and program change (program change can also be sent as an FX command).\"},\"CC#\":{\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"CC number\",\"value\"],\"label\":\"Custom CC (CC:VAL)\",\"description\":\"One of up to 10 custom MIDI CC numbers per instrument with an optional default value, sent with the note-on after program change messages.\"}}}}"),
|
|
3285
|
+
views: /* @__PURE__ */ JSON.parse("{\"project\":{\"rows\":[{\"id\":\"tempo\",\"match\":[{\"x\":0,\"text\":\"TEMPO\"}],\"cells\":[{\"x\":13,\"width\":6,\"key\":\"tempo\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" BPM\",\"label\":\"Tempo (TEMPO)\",\"description\":\"Song speed in beats per minute. [EDIT] pressed rhythmically sets the tempo by tapping.\"}]},{\"id\":\"transpose\",\"match\":[{\"x\":0,\"text\":\"TRANSPOSE\"}],\"cells\":[{\"x\":13,\"width\":2,\"key\":\"transpose\",\"type\":\"transpose\",\"format\":\"hex\",\"label\":\"Project Transpose (TRANSPOSE)\",\"description\":\"Transposes the whole song in semitones (same as the TSP command). Only affects instruments with TRANSP. enabled; applied when [EDIT] is released.\"}]},{\"id\":\"groove\",\"match\":[{\"x\":0,\"text\":\"GROOVE\"}],\"cells\":[{\"x\":13,\"width\":14,\"key\":\"groove\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Default Groove (GROOVE)\",\"description\":\"Groove used when the song plays (number and name); applied when [EDIT] is released. See Groove View.\"}]},{\"id\":\"scale\",\"match\":[{\"x\":0,\"text\":\"SCALE\"}],\"cells\":[{\"x\":13,\"width\":16,\"key\":\"scale\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Default Scale (SCALE)\",\"description\":\"Scale (number, key and name) used when the song plays; applied when [EDIT] is released. See Scale View.\"}]},{\"id\":\"liveQuantize\",\"match\":[{\"x\":0,\"text\":\"LIVE QUANTIZ\"}],\"cells\":[{\"x\":13,\"width\":14,\"key\":\"liveQuantize\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Live Quantize (LIVE QUANTIZE)\",\"description\":\"How long a cued chain waits before starting when playing in live mode.\"}]},{\"id\":\"midi\",\"match\":[{\"x\":0,\"text\":\"MIDI\"},{\"x\":13,\"text\":\"SETTINGS\"}],\"cells\":[{\"x\":13,\"width\":8,\"key\":\"midiSettings\",\"type\":\"action\",\"format\":\"text\",\"label\":\"MIDI Settings\",\"description\":\"Open the MIDI Settings View.\"},{\"x\":22,\"width\":8,\"key\":\"midiMappings\",\"type\":\"action\",\"format\":\"text\",\"label\":\"MIDI Mappings\",\"description\":\"Open the MIDI Mappings View.\"}]},{\"id\":\"name\",\"match\":[{\"x\":0,\"text\":\"NAME\"}],\"cells\":[{\"x\":13,\"width\":12,\"key\":\"name\",\"type\":\"name\",\"format\":\"text\",\"label\":\"Song Name (NAME)\",\"description\":\"Name of the current song, entered before saving.\"}]},{\"id\":\"file\",\"match\":[{\"x\":0,\"text\":\"PROJECT\"},{\"x\":13,\"text\":\"LOAD\"}],\"cells\":[{\"x\":13,\"width\":4,\"key\":\"load\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Load Song\",\"description\":\"Load a song from the SD card.\"},{\"x\":18,\"width\":4,\"key\":\"save\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Save Song\",\"description\":\"Save the current song.\"},{\"x\":23,\"width\":3,\"key\":\"new\",\"type\":\"action\",\"format\":\"text\",\"label\":\"New Song\",\"description\":\"Create a new song.\"}]},{\"id\":\"export\",\"match\":[{\"x\":0,\"text\":\"EXPORT/SHARE\"}],\"cells\":[{\"x\":13,\"width\":6,\"key\":\"render\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Render\",\"description\":\"Open the Render View to render audio.\"},{\"x\":20,\"width\":6,\"key\":\"bundle\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Bundle\",\"description\":\"Bundle the song with the instruments and samples it uses.\"}]},{\"id\":\"clearUnused\",\"match\":[{\"x\":0,\"text\":\"CLEAR UNUSED\"}],\"cells\":[{\"x\":13,\"width\":7,\"key\":\"clearPhrases\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Clear Unused Phrases\",\"description\":\"Frees chains and phrases that are not used in the song.\"},{\"x\":21,\"width\":8,\"key\":\"clearInstTbl\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Clear Unused Instruments/Tables\",\"description\":\"Frees instruments, EQs and tables that are not used in the song.\"}]},{\"id\":\"instPool\",\"match\":[{\"x\":0,\"text\":\"INST. POOL\"}],\"cells\":[{\"x\":13,\"width\":15,\"key\":\"viewInstPool\",\"type\":\"action\",\"format\":\"text\",\"label\":\"View Instrument Pool\",\"description\":\"Go to the Instrument Pool View.\"}]},{\"id\":\"timeStats\",\"match\":[{\"x\":0,\"text\":\"TIME STATS\"}],\"cells\":[{\"x\":13,\"width\":15,\"key\":\"viewTimeStats\",\"type\":\"action\",\"format\":\"text\",\"label\":\"View Time Stats\",\"description\":\"Open the Time Stats View (time spent on the song).\"}]},{\"id\":\"system\",\"match\":[{\"x\":0,\"text\":\"SYSTEM\"},{\"x\":13,\"text\":\"SETTINGS\"}],\"cells\":[{\"x\":13,\"width\":8,\"key\":\"systemSettings\",\"type\":\"action\",\"format\":\"text\",\"label\":\"System Settings\",\"description\":\"Go to the System Settings View.\"},{\"x\":22,\"width\":9,\"key\":\"usbDrive\",\"type\":\"action\",\"format\":\"text\",\"label\":\"USB Drive\",\"description\":\"Puts the M8 in USB drive mode so SD card files can be transferred to a computer.\"}]}]},\"systemsettings\":{\"rows\":[{\"id\":\"backlight\",\"match\":[{\"x\":0,\"text\":\"BACKLIGHT\"}],\"cells\":[{\"x\":15,\"width\":2,\"key\":\"backlight\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Backlight (BACKLIGHT)\",\"description\":\"Backlight LED brightness of the display.\"}]},{\"id\":\"fontOptions\",\"match\":[{\"x\":0,\"text\":\"FONT OPTIONS\"}],\"cells\":[{\"x\":15,\"width\":15,\"key\":\"fontOptions\",\"type\":\"option\",\"format\":\"text\",\"label\":\"Font Options (FONT OPTIONS)\",\"description\":\"Font settings, including a large font mode for readability.\"}]},{\"id\":\"theme\",\"match\":[{\"x\":0,\"text\":\"THEME\"}],\"cells\":[{\"x\":15,\"width\":10,\"key\":\"editTheme\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Theme (EDIT THEME)\",\"description\":\"Open the Theme View.\"}]},{\"id\":\"notePreview\",\"match\":[{\"x\":0,\"text\":\"NOTE PREVIEW\"}],\"cells\":[{\"x\":15,\"width\":3,\"key\":\"notePreview\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Note Preview (NOTE PREVIEW)\",\"description\":\"Plays the note when editing notes in the phrase view.\"}]},{\"id\":\"recCountIn\",\"match\":[{\"x\":0,\"regex\":\"^REC\\\\.\\\\s?(COUNT IN|METRONOME)\\\\s*$\",\"width\":13}],\"cells\":[{\"x\":15,\"width\":6,\"key\":\"recCountIn\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Recording Count-in (REC. COUNT IN)\",\"description\":\"Number of phrases/measures of metronome count-in before recording audio in the Sample Editor or Selection to Sample.\"}]},{\"id\":\"metronomeVol\",\"match\":[{\"x\":0,\"text\":\"METRONOME VOL\"}],\"cells\":[{\"x\":15,\"width\":2,\"key\":\"metronomeVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Metronome Volume (METRONOME VOL)\",\"description\":\"Volume of the metronome sound (edit /System/Metronome.m8i to change the sound).\"}]},{\"id\":\"songTemplate\",\"match\":[{\"x\":0,\"text\":\"SONG TEMPLATE\"}],\"cells\":[{\"x\":15,\"width\":4,\"key\":\"songTemplateSave\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Song Template (SAVE)\",\"description\":\"Use the currently opened song as the template for new songs.\"},{\"x\":20,\"width\":5,\"key\":\"songTemplateClear\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Song Template (CLEAR)\",\"description\":\"Clear the song template.\"}]},{\"id\":\"usbAudioMode\",\"match\":[{\"x\":0,\"text\":\"USB AUDIO MODE\"}],\"cells\":[{\"x\":15,\"width\":14,\"key\":\"usbAudioMode\",\"type\":\"option\",\"format\":\"text\",\"label\":\"USB Audio Mode (USB AUDIO MODE)\",\"description\":\"USB output as stereo or multi-channel (multi-channel sends all 8 tracks and the effects individually, 12 stereo channels).\",\"options\":{\"STEREO OUT\":\"Stereo mix over USB.\"}}]},{\"id\":\"usbMainOut\",\"match\":[{\"x\":0,\"text\":\"USB MAIN OUT\"}],\"cells\":[{\"x\":15,\"width\":6,\"key\":\"usbMainOut\",\"type\":\"option\",\"format\":\"text\",\"label\":\"USB Main Out (USB MAIN OUT)\",\"description\":\"Routing behaviour of USB audio (see the USB audio routing options).\"}]},{\"id\":\"lineInGate\",\"match\":[{\"x\":0,\"text\":\"LINE-IN GATE\"}],\"cells\":[{\"x\":15,\"width\":6,\"key\":\"lineInGate\",\"type\":\"option\",\"format\":\"text\",\"label\":\"Line-in Gate (LINE-IN GATE)\",\"description\":\"Noise gate threshold for the line input, adjustable from -70 dB to -10 dB (OFF disables it).\"}]},{\"id\":\"splashScreen\",\"match\":[{\"x\":0,\"text\":\"SPLASH SCREEN\"}],\"cells\":[{\"x\":15,\"width\":3,\"key\":\"splashScreen\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Splash Screen (SPLASH SCREEN)\",\"description\":\"Show the M8 logo and play the start-up sound when turning on the device.\"}]},{\"id\":\"hpProtection\",\"match\":[{\"x\":0,\"text\":\"HP PROTECTION\"}],\"cells\":[{\"x\":15,\"width\":3,\"key\":\"hpProtection\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Headphone Protection (HP PROTECTION)\",\"description\":\"Limits the headphone output volume to F0 when a pack is unplugged and re-inserted.\"}]},{\"id\":\"keyDelayRep\",\"match\":[{\"x\":0,\"text\":\"KEY DELAY:REP\"}],\"cells\":[{\"x\":15,\"width\":7,\"key\":\"keyDelayRep\",\"type\":\"parameter\",\"format\":\"decimalPair\",\"unit\":\" ms\",\"parts\":[\"delay\",\"repeat\"],\"label\":\"Key Delay:Repeat (KEY DELAY:REP)\",\"description\":\"Key repeat timing in milliseconds: delay before a held key starts repeating, then the time between repeats.\"}]},{\"id\":\"battCharging\",\"match\":[{\"x\":0,\"regex\":\"^BATT\\\\.\\\\s?(CHARGING|STATUS)\\\\s*$\",\"width\":14}],\"cells\":[{\"x\":15,\"width\":14,\"key\":\"battCharging\",\"type\":\"option\",\"format\":\"text\",\"label\":\"Battery Charging (BATT. CHARGING / STATUS)\",\"description\":\"Whether the battery charges while the M8 is on and USB is connected (turn off to reduce power drawn from the host); also shows the current charging status.\"}]}]},\"effectsettings\":{\"sections\":[\"MODFX\",\"DELAY\",\"REVERB\"],\"rows\":[{\"id\":\"modfxType\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"MOD TYPE\"}],\"cells\":[{\"x\":21,\"width\":10,\"key\":\"modfxType\",\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"ModFX Type (MOD TYPE)\",\"description\":\"ModFX effect: Chorus, Phaser or Flanger (also sets the phase position).\",\"options\":{\"CHORUS\":\"Stereo chorus.\",\"PHASER\":\"Stereo phaser.\",\"FLANGER\":\"Stereo flanger.\"}}]},{\"id\":\"modfxInputEq\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"INPUT EQ\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"modfxInputEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Input EQ (INPUT EQ)\",\"description\":\"Open the EQ editor for this effect's input.\"}]},{\"id\":\"modfxDepthFreq\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"MOD DEPTH:FRQ\"}],\"cells\":[{\"x\":21,\"width\":5,\"key\":\"modfxDepthFreq\",\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"mod depth\",\"mod frequency\"],\"label\":\"ModFX Mod Depth:Frequency (MOD DEPTH:FRQ)\",\"description\":\"Amount of modulation in the stereo signal (first value) and speed of the modulation (second value).\"}]},{\"id\":\"modfxWidth\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"STEREO WIDTH\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"modfxWidth\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Stereo Width (STEREO WIDTH)\",\"description\":\"Stereo width: 00 is mono, FF is stereo.\"}]},{\"id\":\"modfxReverbSend\",\"section\":\"MODFX\",\"match\":[{\"x\":7,\"text\":\"REVERB SEND\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"modfxReverbSend\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Reverb Send (REVERB SEND)\",\"description\":\"Amount of this effect sent to the reverb.\"}]},{\"id\":\"delayInputEq\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"INPUT EQ\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"delayInputEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Input EQ (INPUT EQ)\",\"description\":\"Open the EQ editor for this effect's input.\"}]},{\"id\":\"delayTime\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"TIME L:R\"}],\"cells\":[{\"x\":21,\"width\":5,\"key\":\"delayTime\",\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"left time\",\"right time\"],\"label\":\"Delay Time L:R (TIME L:R)\",\"description\":\"Delay time for the left and right channels: first digit in beats, second digit in fractions of a beat (40 is 4 beats).\"}]},{\"id\":\"delayFeedback\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"FEEDBACK\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"delayFeedback\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Feedback (FEEDBACK)\",\"description\":\"Amount of the delayed signal fed back into the delay.\"}]},{\"id\":\"delayWidth\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"STEREO WIDTH\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"delayWidth\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Stereo Width (STEREO WIDTH)\",\"description\":\"Stereo width: 00 is mono, FF is stereo.\"}]},{\"id\":\"delayReverbSend\",\"section\":\"DELAY\",\"match\":[{\"x\":7,\"text\":\"REVERB SEND\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"delayReverbSend\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Reverb Send (REVERB SEND)\",\"description\":\"Amount of this effect sent to the reverb.\"}]},{\"id\":\"reverbInputEq\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"INPUT EQ\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"reverbInputEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Input EQ (INPUT EQ)\",\"description\":\"Open the EQ editor for this effect's input.\"}]},{\"id\":\"reverbRoomSize\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"ROOM SIZE\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"reverbRoomSize\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Room Size (ROOM SIZE)\",\"description\":\"Size of the reverb room.\"}]},{\"id\":\"reverbDecayShimmer\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"DECAY:SHIMMER\"}],\"cells\":[{\"x\":21,\"width\":5,\"key\":\"reverbDecayShimmer\",\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"decay\",\"shimmer\"],\"label\":\"Reverb Decay:Shimmer (DECAY:SHIMMER)\",\"description\":\"Reverb decay time (first value) and shimmer amount (second value).\"}]},{\"id\":\"reverbDepthFreq\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"MOD DEPTH:FRQ\"}],\"cells\":[{\"x\":21,\"width\":5,\"key\":\"reverbDepthFreq\",\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"mod depth\",\"mod frequency\"],\"label\":\"Reverb Mod Depth:Frequency (MOD DEPTH:FRQ)\",\"description\":\"Reverb modulation depth (first value) and frequency (second value).\"}]},{\"id\":\"reverbWidth\",\"section\":\"REVERB\",\"match\":[{\"x\":7,\"text\":\"STEREO WIDTH\"}],\"cells\":[{\"x\":21,\"width\":2,\"key\":\"reverbWidth\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Stereo Width (STEREO WIDTH)\",\"description\":\"Stereo width: 00 is mono, FF is stereo.\"}]}]},\"mixer\":{\"rows\":[{\"id\":\"speaker\",\"match\":[{\"x\":0,\"text\":\"SPEAKER\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"speakerVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Speaker Volume (SPEAKER VOL)\",\"description\":\"Volume of the built-in speaker.\"}]},{\"id\":\"outputVol\",\"match\":[{\"x\":0,\"text\":\"OUTPUT VOL\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"outputVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Output Volume (OUTPUT VOL)\",\"description\":\"Volume of the audio output (headphones / line out).\"}]},{\"id\":\"tracks\",\"match\":[{\"x\":0,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2},{\"x\":21,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2}],\"cells\":[{\"x\":0,\"width\":2,\"key\":\"track1\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 1 Volume\",\"meta\":{\"trackIndex\":1},\"description\":\"Volume of track 1. Instrument volumes are applied on top; the track's send levels are set in the instruments.\"},{\"x\":3,\"width\":2,\"key\":\"track2\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 2 Volume\",\"meta\":{\"trackIndex\":2},\"description\":\"Volume of track 2.\"},{\"x\":6,\"width\":2,\"key\":\"track3\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 3 Volume\",\"meta\":{\"trackIndex\":3},\"description\":\"Volume of track 3.\"},{\"x\":9,\"width\":2,\"key\":\"track4\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 4 Volume\",\"meta\":{\"trackIndex\":4},\"description\":\"Volume of track 4.\"},{\"x\":12,\"width\":2,\"key\":\"track5\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 5 Volume\",\"meta\":{\"trackIndex\":5},\"description\":\"Volume of track 5.\"},{\"x\":15,\"width\":2,\"key\":\"track6\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 6 Volume\",\"meta\":{\"trackIndex\":6},\"description\":\"Volume of track 6.\"},{\"x\":18,\"width\":2,\"key\":\"track7\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 7 Volume\",\"meta\":{\"trackIndex\":7},\"description\":\"Volume of track 7.\"},{\"x\":21,\"width\":2,\"key\":\"track8\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Track 8 Volume\",\"meta\":{\"trackIndex\":8},\"description\":\"Volume of track 8.\"}]},{\"id\":\"eq\",\"match\":[{\"x\":27,\"text\":\"EQ\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"mixEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Main Mix EQ (EQ)\",\"description\":\"Open the main mix EQ editor ([EDIT] or [SHIFT]+[RIGHT]).\"}]},{\"id\":\"levels\",\"match\":[{\"x\":0,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2},{\"x\":3,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2},{\"x\":6,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2},{\"x\":12,\"regex\":\"^[0-9A-F]{2}$\",\"width\":2}],\"cells\":[{\"x\":0,\"width\":2,\"key\":\"modfxVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"ModFX Volume (MX)\",\"description\":\"Output level of the ModFX send effect.\"},{\"x\":3,\"width\":2,\"key\":\"delayVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Delay Volume (DE)\",\"description\":\"Output level of the delay send effect.\"},{\"x\":6,\"width\":2,\"key\":\"reverbVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Reverb Volume (RE)\",\"description\":\"Output level of the reverb send effect.\"},{\"x\":12,\"width\":2,\"key\":\"inputVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input Volume (INPUT)\",\"description\":\"Volume of the analog input for monitoring. In dual-mono mode this is the left channel.\"},{\"x\":15,\"width\":2,\"key\":\"inputVol2\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input Volume, 2nd channel\",\"description\":\"Enables dual-mono input mode when set (right channel volume); clear with [EDIT]+[OPTION] to disable.\"},{\"x\":18,\"width\":2,\"key\":\"usbVol\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"USB Input Volume (USB)\",\"description\":\"Volume of anything the USB host computer sends to the M8.\"},{\"x\":27,\"width\":2,\"key\":\"mainVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Main Volume (MIX)\",\"description\":\"Main song volume, applied after the limiter, DJ filter and OTT. [EDIT] or [SHIFT]+[RIGHT] opens the Mix Scope.\"}]},{\"id\":\"limiter\",\"match\":[{\"x\":0,\"text\":\"MX\"},{\"x\":3,\"text\":\"DE\"},{\"x\":6,\"text\":\"RE\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"limiter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter (LIM)\",\"description\":\"Main mix limiter amount; the limiter is engaged when the value is above 00. [EDIT] or [SHIFT]+[RIGHT] opens the Limiter Scope.\"}]},{\"id\":\"sendModfx\",\"match\":[{\"x\":9,\"text\":\"MX\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"inputModfx\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input ModFX Send (INPUT MX)\",\"description\":\"How much of the analog input goes to the ModFX effect.\"},{\"x\":18,\"width\":2,\"key\":\"usbModfx\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"USB Input ModFX Send (USB MX)\",\"description\":\"How much of the USB input goes to the ModFX effect.\"},{\"x\":27,\"width\":2,\"key\":\"djFilter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"DJ Filter (DJF)\",\"description\":\"DJ filter cutoff: 80 is off, below 80 low-pass (or band-stop), above 80 high-pass. Mode and options are in the Scope View.\"}]},{\"id\":\"sendDelay\",\"match\":[{\"x\":9,\"text\":\"DE\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"inputDelay\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input Delay Send (INPUT DE)\",\"description\":\"How much of the analog input goes to the delay effect.\"},{\"x\":18,\"width\":2,\"key\":\"usbDelay\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"USB Input Delay Send (USB DE)\",\"description\":\"How much of the USB input goes to the delay effect.\"},{\"x\":27,\"width\":2,\"key\":\"ott\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"OTT (OTT)\",\"description\":\"Over The Top multi-band compression mixed in parallel: 00 to 80 mixes it in; from 80 and above the main mix is faded out.\"}]},{\"id\":\"sendReverb\",\"match\":[{\"x\":9,\"text\":\"RE\"}],\"cells\":[{\"x\":12,\"width\":2,\"key\":\"inputReverb\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"Analog Input Reverb Send (INPUT RE)\",\"description\":\"How much of the analog input goes to the reverb effect.\"},{\"x\":18,\"width\":2,\"key\":\"usbReverb\",\"type\":\"volume\",\"format\":\"hex\",\"label\":\"USB Input Reverb Send (USB RE)\",\"description\":\"How much of the USB input goes to the reverb effect.\"}]}]},\"mixeq\":{\"rows\":[{\"id\":\"gain\",\"match\":[{\"x\":0,\"text\":\"GAIN\"}],\"cells\":[{\"x\":5,\"width\":6,\"key\":\"lowGain\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" dB\",\"label\":\"LOW Gain\",\"description\":\"Boost (positive) or cut (negative) applied by the LOW band, in decibels.\"},{\"x\":16,\"width\":6,\"key\":\"midGain\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" dB\",\"label\":\"MID Gain\",\"description\":\"Boost (positive) or cut (negative) applied by the MID band, in decibels.\"},{\"x\":27,\"width\":6,\"key\":\"highGain\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" dB\",\"label\":\"HIGH Gain\",\"description\":\"Boost (positive) or cut (negative) applied by the HIGH band, in decibels.\"}]},{\"id\":\"freq\",\"match\":[{\"x\":0,\"text\":\"FREQ\"}],\"cells\":[{\"x\":6,\"width\":5,\"key\":\"lowFreq\",\"type\":\"parameter\",\"format\":\"decimal\",\"unit\":\" Hz\",\"label\":\"LOW Frequency\",\"description\":\"Centre (or corner) frequency of the LOW band.\"},{\"x\":17,\"width\":5,\"key\":\"midFreq\",\"type\":\"parameter\",\"format\":\"decimal\",\"unit\":\" Hz\",\"label\":\"MID Frequency\",\"description\":\"Centre (or corner) frequency of the MID band.\"},{\"x\":28,\"width\":5,\"key\":\"highFreq\",\"type\":\"parameter\",\"format\":\"decimal\",\"unit\":\" Hz\",\"label\":\"HIGH Frequency\",\"description\":\"Centre (or corner) frequency of the HIGH band.\"}]},{\"id\":\"q\",\"match\":[{\"x\":0,\"text\":\"Q\"},{\"x\":1,\"regex\":\"^\\\\s?$\",\"width\":1}],\"cells\":[{\"x\":6,\"width\":3,\"key\":\"lowQ\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"LOW Q\",\"description\":\"Quality factor (bandwidth) of the LOW band: higher values narrow it.\"},{\"x\":17,\"width\":3,\"key\":\"midQ\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"MID Q\",\"description\":\"Quality factor (bandwidth) of the MID band: higher values narrow it.\"},{\"x\":28,\"width\":3,\"key\":\"highQ\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"HIGH Q\",\"description\":\"Quality factor (bandwidth) of the HIGH band: higher values narrow it.\"}]},{\"id\":\"type\",\"match\":[{\"x\":0,\"text\":\"TYPE\"}],\"cells\":[{\"x\":6,\"width\":9,\"key\":\"lowType\",\"type\":\"option\",\"format\":\"text\",\"label\":\"LOW Type\",\"description\":\"Filter shape of the LOW band.\",\"options\":{\"LOWCUT\":\"Removes frequencies below the cutoff.\",\"LOWSHELF\":\"Boosts or cuts frequencies below the shelf frequency.\",\"BELL\":\"Peaking filter: boosts or cuts around the centre frequency.\",\"BANDPASS\":\"Passes frequencies around the centre frequency, attenuating both sides.\",\"HI.SHELF\":\"Boosts or cuts frequencies above the shelf frequency.\",\"HI.CUT\":\"Attenuates or removes frequencies above the cutoff.\",\"ALLPASS\":\"Passes all frequencies at equal gain while shifting their phase.\"}},{\"x\":17,\"width\":9,\"key\":\"midType\",\"type\":\"option\",\"format\":\"text\",\"label\":\"MID Type\",\"description\":\"Filter shape of the MID band.\",\"options\":{\"LOWCUT\":\"Removes frequencies below the cutoff.\",\"LOWSHELF\":\"Boosts or cuts frequencies below the shelf frequency.\",\"BELL\":\"Peaking filter: boosts or cuts around the centre frequency.\",\"BANDPASS\":\"Passes frequencies around the centre frequency, attenuating both sides.\",\"HI.SHELF\":\"Boosts or cuts frequencies above the shelf frequency.\",\"HI.CUT\":\"Attenuates or removes frequencies above the cutoff.\",\"ALLPASS\":\"Passes all frequencies at equal gain while shifting their phase.\"}},{\"x\":28,\"width\":9,\"key\":\"highType\",\"type\":\"option\",\"format\":\"text\",\"label\":\"HIGH Type\",\"description\":\"Filter shape of the HIGH band.\",\"options\":{\"LOWCUT\":\"Removes frequencies below the cutoff.\",\"LOWSHELF\":\"Boosts or cuts frequencies below the shelf frequency.\",\"BELL\":\"Peaking filter: boosts or cuts around the centre frequency.\",\"BANDPASS\":\"Passes frequencies around the centre frequency, attenuating both sides.\",\"HI.SHELF\":\"Boosts or cuts frequencies above the shelf frequency.\",\"HI.CUT\":\"Attenuates or removes frequencies above the cutoff.\",\"ALLPASS\":\"Passes all frequencies at equal gain while shifting their phase.\"}}]},{\"id\":\"mode\",\"match\":[{\"x\":0,\"text\":\"MODE\"}],\"cells\":[{\"x\":6,\"width\":6,\"key\":\"lowMode\",\"type\":\"option\",\"format\":\"text\",\"label\":\"LOW Mode\",\"description\":\"How the LOW band is applied to the stereo signal.\",\"options\":{\"STEREO\":\"Processes left and right identically.\",\"MID\":\"Affects only the mid (centre) information.\",\"SIDE\":\"Affects only the side information (difference between left and right).\",\"LEFT\":\"Affects only the left channel.\",\"RIGHT\":\"Affects only the right channel.\"}},{\"x\":17,\"width\":6,\"key\":\"midMode\",\"type\":\"option\",\"format\":\"text\",\"label\":\"MID Mode\",\"description\":\"How the MID band is applied to the stereo signal.\",\"options\":{\"STEREO\":\"Processes left and right identically.\",\"MID\":\"Affects only the mid (centre) information.\",\"SIDE\":\"Affects only the side information (difference between left and right).\",\"LEFT\":\"Affects only the left channel.\",\"RIGHT\":\"Affects only the right channel.\"}},{\"x\":28,\"width\":6,\"key\":\"highMode\",\"type\":\"option\",\"format\":\"text\",\"label\":\"HIGH Mode\",\"description\":\"How the HIGH band is applied to the stereo signal.\",\"options\":{\"STEREO\":\"Processes left and right identically.\",\"MID\":\"Affects only the mid (centre) information.\",\"SIDE\":\"Affects only the side information (difference between left and right).\",\"LEFT\":\"Affects only the left channel.\",\"RIGHT\":\"Affects only the right channel.\"}}]}]},\"modfxeq\":{\"extends\":\"mixeq\"},\"delayeq\":{\"extends\":\"mixeq\"},\"reverbeq\":{\"extends\":\"mixeq\"},\"mixscope\":{\"rows\":[{\"id\":\"limiterAtkRel\",\"match\":[{\"x\":9,\"text\":\"ATK\"},{\"x\":16,\"text\":\"REL\"},{\"x\":23,\"text\":\"LIM\"}],\"cells\":[{\"x\":13,\"width\":2,\"key\":\"attack\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter Attack (ATK)\",\"description\":\"Limiter attack time from 0 to 100 ms (see the on-screen help text for the conversion to milliseconds).\"},{\"x\":20,\"width\":2,\"key\":\"release\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter Release (REL)\",\"description\":\"Limiter release time from 4 to 1000 ms; 00 activates AUTO mode (100-900 ms depending on the compression amount).\"},{\"x\":27,\"width\":2,\"key\":\"limiter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter (LIM)\",\"description\":\"Limiter amount.\"}]},{\"id\":\"zoomPeak\",\"match\":[{\"x\":0,\"text\":\"ZOOM\"}],\"cells\":[{\"x\":5,\"width\":5,\"key\":\"zoom\",\"type\":\"parameter\",\"format\":\"text\",\"label\":\"Zoom (ZOOM)\",\"description\":\"Lower limit of the scope histogram, in decibels.\"},{\"x\":20,\"width\":6,\"key\":\"peak\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" dB\",\"label\":\"Peak (PEAK)\",\"description\":\"Current peak level of the main mix in dB. Resets when MIX or LIM change; clear it with [OPT]+[EDIT].\"}]},{\"id\":\"eq\",\"match\":[{\"x\":27,\"text\":\"EQ\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"mixEq\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Main Mix EQ (EQ)\",\"description\":\"Open the main mix EQ editor.\"}]},{\"id\":\"softClip\",\"match\":[{\"x\":9,\"text\":\"SOFT CLIP\"}],\"cells\":[{\"x\":19,\"width\":3,\"key\":\"softClip\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Soft Clip (SOFT CLIP)\",\"description\":\"Gentle saturation after the limiter to prevent harsh clipping; raise MIX to exaggerate it.\"},{\"x\":27,\"width\":2,\"key\":\"mainVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Main Volume (MIX)\",\"description\":\"Main mix / song volume, applied after the limiter stage.\"}]},{\"id\":\"mix\",\"match\":[{\"x\":23,\"text\":\"MIX\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"mainVol\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Main Volume (MIX)\",\"description\":\"Main mix / song volume, applied after the limiter stage.\"}]},{\"id\":\"lim\",\"match\":[{\"x\":23,\"text\":\"LIM\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"limiter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter (LIM)\",\"description\":\"Limiter amount.\"}]},{\"id\":\"djf\",\"match\":[{\"x\":23,\"text\":\"DJF\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"djFilter\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"DJ Filter (DJF)\",\"description\":\"DJ filter cutoff: 80 is off, 00-80 low-pass, 80-FF high-pass (mode set with TYPE).\"}]},{\"id\":\"ott\",\"match\":[{\"x\":23,\"text\":\"OTT\"}],\"cells\":[{\"x\":27,\"width\":2,\"key\":\"ott\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"OTT (OTT)\",\"description\":\"OTT mix amount; from 80 and above the main mix volume is faded out.\"}]}],\"zones\":[{\"id\":\"right\",\"labelX\":23,\"labelWidth\":4,\"x\":27,\"width\":6}],\"vocabulary\":{\"ATK\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter Attack (ATK)\",\"description\":\"Limiter attack time from 0 to 100 ms (see the on-screen help text for the conversion).\"},\"REL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Limiter Release (REL)\",\"description\":\"Limiter release time from 4 to 1000 ms; 00 activates AUTO mode (100-900 ms depending on the compression amount).\"},\"TYPE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"DJ Filter Type (TYPE)\",\"description\":\"DJ filter type: low-pass/high-pass, low-pass/band-stop or band-stop/high-pass.\"},\"RES\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"DJ Filter Resonance (RES)\",\"description\":\"Resonance of the DJ filter.\"},\"TIME\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"OTT Time (TIME)\",\"description\":\"OTT compressor envelope time as a percentage from 10% to 1000%.\"},\"COLOR\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"OTT Color (COLOR)\",\"description\":\"OTT compressor bands and low/high gains: above 80 shifts toward treble, below 80 toward bass.\"}}},\"limiterscope\":{\"extends\":\"mixscope\"},\"inst\":{\"rows\":[{\"id\":\"type\",\"match\":[{\"x\":0,\"text\":\"TYPE\"}],\"cells\":[{\"x\":8,\"width\":13,\"key\":\"instrumentType\",\"type\":\"instrumentType\",\"format\":\"text\",\"label\":\"Instrument Type (TYPE)\",\"description\":\"Kind of instrument in this slot: Wavsynth, Macrosynth, Sampler, FM Synth, Hypersynth, External Instrument, MIDI Out (or NONE for an unused slot). Changing it changes the parameters below.\"},{\"x\":22,\"width\":4,\"key\":\"load\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Load Preset (LOAD)\",\"description\":\"Load an instrument preset from the SD card.\"},{\"x\":27,\"width\":4,\"key\":\"save\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Save Preset (SAVE)\",\"description\":\"Save this instrument as a preset on the SD card.\"}]},{\"id\":\"name\",\"match\":[{\"x\":0,\"text\":\"NAME\"}],\"cells\":[{\"x\":8,\"width\":12,\"key\":\"name\",\"type\":\"name\",\"format\":\"text\",\"label\":\"Instrument Name (NAME)\",\"description\":\"Name of the instrument: helps keep the song organised when browsing, saving or bundling instruments.\"}]},{\"id\":\"transp\",\"match\":[{\"x\":0,\"text\":\"TRANSP.\"}],\"cells\":[{\"x\":8,\"width\":3,\"key\":\"transpose\",\"type\":\"onOff\",\"format\":\"text\",\"label\":\"Transpose Enabled (TRANSP.)\",\"description\":\"Enable or disable note transposition from scales, chain transpose columns and the project transpose for this instrument (turn off for percussive or effect instruments).\"},{\"x\":21,\"width\":2,\"key\":\"tableTic\",\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Table Tick (TBL. TIC)\",\"description\":\"Default speed at which this instrument's table advances: 01 is one tick per step, 02 two ticks per step. Can be overridden by the TIC command.\"},{\"x\":29,\"width\":2,\"key\":\"eq\",\"type\":\"eqSlot\",\"format\":\"hex\",\"label\":\"EQ Slot (EQ)\",\"description\":\"EQ bank assigned to this instrument (-- for none). [EDIT] or [SHIFT]+[RIGHT] opens the EQ editor.\"}]}],\"zones\":[{\"id\":\"left\",\"labelX\":0,\"labelWidth\":8,\"x\":8,\"width\":24},{\"id\":\"right\",\"labelX\":18,\"labelWidth\":4,\"x\":22,\"width\":11}],\"operators\":{\"instrument\":\"fmsynth\",\"x\":8,\"step\":6,\"width\":5,\"letters\":[\"A\",\"B\",\"C\",\"D\"]},\"vocabularyFrom\":\"instrumentTypes\"},\"instmods\":{\"slotLabel\":\"MOD\\\\d\",\"zones\":[{\"id\":\"left\",\"labelX\":0,\"labelWidth\":4,\"x\":5,\"width\":10},{\"id\":\"right\",\"labelX\":16,\"labelWidth\":4,\"x\":21,\"width\":10}],\"vocabulary\":{\"MOD#\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Modulator Type\",\"description\":\"Type of this modulation slot: AHD envelope, ADSR envelope, DRUM envelope, LFO, TRIG envelope or TRACKING. Slots can modulate their neighbour (Mod 1 affects Mod 2, 2→3, 3→4, 4→1).\",\"options\":{\"AHD ENV\":\"Attack Hold Decay envelope based on tempo.\",\"ADSR ENV\":\"Traditional Attack Decay Sustain Release envelope.\",\"DRUM ENV\":\"Sharp peak and swelling hold envelope for percussive elements.\",\"LFO\":\"Tempo-synced low frequency oscillator.\",\"TRIG ENV\":\"AHD envelope triggered by another playing track or instrument.\",\"TRACKING\":\"Modulates an instrument parameter from notes or velocities.\",\"OFF\":\"Slot unused.\"}},\"DEST\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Destination (DEST)\",\"description\":\"Instrument parameter this modulator controls. MOD AMT, MOD RATE or MOD BOTH modulate the neighbouring modulator's amount, rate or both.\"},\"SRC\":{\"type\":\"parameter\",\"format\":\"hexOption\",\"label\":\"Source (SRC)\",\"description\":\"Modulation source. Trig envelope: an instrument number (00-7F) or a whole track (80-87 = tracks 1-8). Tracking: NOTE, VELOCITY or VELOCITY TAKEOVER (velocity no longer affects instrument volume).\"},\"AMT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Amount (AMT)\",\"description\":\"How strongly the modulator is applied to the destination.\"},\"ATK\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Attack (ATK)\",\"description\":\"Time to reach the amount (in ticks, relative to tempo).\"},\"HOLD\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Hold (HOLD)\",\"description\":\"Time to wait after the attack before decaying (in ticks).\"},\"DEC\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Decay (DEC)\",\"description\":\"Time to fall back (AHD/Drum: to zero; ADSR: to the sustain level), in ticks.\"},\"SUS\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Sustain (SUS)\",\"description\":\"Level held while the note is playing (ADSR).\"},\"REL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Release (REL)\",\"description\":\"Time to fall back to zero after the note is released (ADSR); needs an OFF note or FX command.\"},\"PEAK\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Peak (PEAK)\",\"description\":\"Shape of the initial transient (drum envelope); modifies the duck amount and peak time.\"},\"BODY\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Body (BODY)\",\"description\":\"Time to hold the modulation before decaying (drum envelope).\"},\"OSC\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"LFO Shape (OSC)\",\"description\":\"LFO shape: triangle, sine, ramp down/up, exponential down/up, square down/up, random, drunk. The 'T' variants run in ticks (much faster).\",\"options\":{\"TRI\":\"Triangle.\",\"SIN\":\"Sine.\",\"RAMP DN\":\"Ramp down.\",\"RAMP UP\":\"Ramp up.\",\"EXP DN\":\"Exponential down.\",\"EXP UP\":\"Exponential up.\",\"SQU DN\":\"Square down.\",\"SQU UP\":\"Square up.\",\"RANDOM\":\"Random values.\",\"DRUNK\":\"Random walk.\"}},\"TRIG\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"LFO Trigger (TRIG)\",\"description\":\"How the LFO reacts when the instrument triggers and when the shape ends.\",\"options\":{\"FREE\":\"Loop the shape and don't reset on new notes.\",\"RETRIG\":\"Loop the shape and reset on each instrument trigger.\",\"HOLD\":\"Hold the last value of the shape.\",\"ONCE\":\"Play the shape once and reset to the start value.\"}},\"FREQ\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"LFO Frequency (FREQ)\",\"description\":\"Rate of the LFO in steps (16th notes), or in ticks for the 'T' shapes.\"},\"LVAL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Low Value (LVAL)\",\"description\":\"Lowest value of the source range scaled to the destination (tracking). Can be higher than HVAL to invert the range.\"},\"HVAL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"High Value (HVAL)\",\"description\":\"Highest value of the source range scaled to the destination (tracking).\"}}},\"scale\":{\"notes\":\"Only the rows below the 12 interval rows; the intervals themselves are grid columns in m8-view-context.json.\",\"rows\":[{\"id\":\"key\",\"match\":[{\"x\":0,\"text\":\"KEY\"}],\"cells\":[{\"x\":6,\"width\":2,\"key\":\"key\",\"type\":\"option\",\"format\":\"text\",\"label\":\"Key (KEY)\",\"description\":\"Global key: the root note of the default scale (can be overridden per track with SCA / SCG).\"}]},{\"id\":\"tune\",\"match\":[{\"x\":0,\"text\":\"TUNE\"}],\"cells\":[{\"x\":6,\"width\":6,\"key\":\"tune\",\"type\":\"parameter\",\"format\":\"float\",\"unit\":\" Hz\",\"label\":\"Tuning (TUNE)\",\"description\":\"Reference pitch of A4 in Hz (440.00 is standard).\"}]},{\"id\":\"name\",\"match\":[{\"x\":0,\"text\":\"NAME\"}],\"cells\":[{\"x\":6,\"width\":16,\"key\":\"name\",\"type\":\"name\",\"format\":\"text\",\"label\":\"Scale Name (NAME)\",\"description\":\"Name of this scale (up to 16 characters); 92 factory scales load from /Scales/Factory.\"}]},{\"id\":\"file\",\"match\":[{\"x\":6,\"text\":\"LOAD\"},{\"x\":11,\"text\":\"SAVE\"}],\"cells\":[{\"x\":6,\"width\":4,\"key\":\"load\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Load Scale (LOAD)\",\"description\":\"Load a scale from the SD card.\"},{\"x\":11,\"width\":4,\"key\":\"save\",\"type\":\"action\",\"format\":\"text\",\"label\":\"Save Scale (SAVE)\",\"description\":\"Save this scale to the SD card.\"}]}]},\"loadinstrument\":{\"kind\":\"browser\",\"browserFor\":\"instrument preset\"},\"selectsavedirectory\":{\"kind\":\"browser\",\"browserFor\":\"save location\"},\"createdirectory\":{\"kind\":\"text\",\"fieldLabel\":\"Directory Name\",\"description\":\"Name of the directory to create on the SD card.\"}}"),
|
|
3286
|
+
instrumentTypes: /* @__PURE__ */ JSON.parse("{\"common\":{\"name\":\"Common\",\"description\":\"Parameters shared by most instrument types.\",\"params\":{\"FILTER\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Filter Type (FILTER)\",\"description\":\"Multi-mode filter type: low-pass, high-pass, band-pass, band-stop, LP>HP (low-pass with RES controlling a 1-pole high-pass), ZDF low-pass, ZDF high-pass.\"},\"CUTOFF\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Filter Cutoff (CUTOFF)\",\"description\":\"Filter cutoff frequency.\"},\"RES\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Filter Resonance (RES)\",\"description\":\"Filter resonance amount.\"},\"AMP\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Amplification (AMP)\",\"description\":\"Amplifies the signal; values above the maximum level are handled according to LIM.\"},\"LIM\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Limit Mode (LIM)\",\"description\":\"Limit / clipping behaviour of the amplified signal.\",\"options\":{\"CLIP\":\"Values above the maximum level are clipped.\",\"SIN\":\"The waveform is fed through a sine function.\",\"FOLD\":\"Values above the maximum level are folded back into themselves.\",\"WRAP\":\"Values above the maximum level are wrapped vertically.\",\"POST\":\"Amplification applied with hard-clipping after the filter stage.\",\"POST:AD\":\"Post filter amplification with soft-clipping.\",\"POST:W1\":\"Post filter folding distortion.\",\"POST:W2\":\"Post filter folding distortion.\",\"POST:W3\":\"Post filter folding distortion.\"}},\"PAN\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Pan (PAN)\",\"description\":\"Stereo position of the instrument (80 is centre).\"},\"DRY\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Dry Volume (DRY)\",\"description\":\"Dry volume sent to the mixer channel.\"},\"MFX\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"ModFX Send (MFX)\",\"description\":\"ModFX send effect volume.\"},\"DEL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Delay Send (DEL)\",\"description\":\"Delay send effect volume.\"},\"REV\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Reverb Send (REV)\",\"description\":\"Reverb send effect volume.\"}}},\"wavsynth\":{\"name\":\"Wavsynth\",\"description\":\"Wave table synthesizer and noise generator: an 8-bit sample buffer generated in real time from one of 9 basic shapes (repeated, skewed, mirrored, filtered, overdriven) or one of 61 built-in wave tables of 64 waveforms each.\",\"params\":{\"SHAPE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Shape (SHAPE)\",\"description\":\"Base waveform: PULSE 12% to 75%, SAW, TRIANGLE, SINE, NOISE PITCHED, NOISE, or WT wave tables. For PWM set PULSE 50% and adjust MIRROR (smoothness set by SIZE).\"},\"SIZE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Size (SIZE)\",\"description\":\"Horizontal size of the waveform (number of samples).\"},\"MULT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Multiply (MULT)\",\"description\":\"Multiplies the waveform by adding repeats of the shape; can sound like hard sync.\"},\"WARP\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Warp (WARP)\",\"description\":\"Pushes the shape to one side of the wave table.\"},\"SCAN\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Scan / Mirror (SCAN)\",\"description\":\"Shapes 0-8: mirrors the waveform at the given position (0-200%). Wave tables: scans through the 64 waveforms.\"},\"FILTER\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Filter Type (FILTER)\",\"description\":\"Multi-mode filter type, plus 4 modes that apply the filter into the waveform: WAV LP, WAV HP, WAV BP, WAV BS.\"}}},\"macrosynth\":{\"name\":\"Macrosynth\",\"description\":\"44 engines ('shapes') from basic analog to 2-op FM, physical modelling and percussion; TIMBRE and COLOR change meaning per shape.\",\"params\":{\"SHAPE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Shape (SHAPE)\",\"description\":\"One of the 44 Macrosynth engines (see the Macrosynth Models appendix).\"},\"TIMBRE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Timbre (TIMBRE)\",\"description\":\"First parameter of the selected shape.\"},\"COLOR\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Color (COLOR)\",\"description\":\"Second parameter of the selected shape.\"},\"DEGRADE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Degrade (DEGRADE)\",\"description\":\"Sample rate reduction effect.\"},\"REDUX\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Redux (REDUX)\",\"description\":\"Bit rate reduction effect.\"}}},\"sampler\":{\"name\":\"Sampler\",\"description\":\"Sample player, editor and recorder for 1 or 2 channel PCM .wav files.\",\"params\":{\"SAMPLE\":{\"type\":\"name\",\"format\":\"text\",\"label\":\"Sample (SAMPLE)\",\"description\":\"The loaded sample; use LOAD to browse for one, REC. to record or EDIT to open the Sample Editor.\"},\"SLICE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Slice (SLICE)\",\"description\":\"Slices the sample into equal sections, mapped from the lowest octave (C-1); 01 FILE uses the markers stored in the file.\"},\"PLAY\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Play Mode (PLAY)\",\"description\":\"Play direction and loop mode.\",\"options\":{\"FWD\":\"Forward, no loop.\",\"REV\":\"Reverse, no loop.\",\"FWDLOOP\":\"Looping forward.\",\"REVLOOP\":\"Looping reverse.\",\"FWD PP\":\"Ping-pong looping, forward first.\",\"REV PP\":\"Ping-pong looping, reverse first.\",\"OSC\":\"Oscillator mode: ignores the start position and doesn't restart on retrigger.\",\"OSC REV\":\"Oscillator mode, reverse.\",\"OSC PP\":\"Oscillator mode, ping-pong.\",\"REPITCH\":\"Pitches the sample from the song tempo (adjust with STEPS/BPM).\"}},\"START\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Start (START)\",\"description\":\"Sample start position (ignored in OSC play modes).\"},\"LOOP ST.\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Loop Start (LOOP ST.)\",\"description\":\"Where the sample loops back to when it reaches the end in a looping play mode.\"},\"LOOP ST\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Loop Start (LOOP ST)\",\"description\":\"Where the sample loops back to when it reaches the end in a looping play mode.\"},\"LEN\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Length (LEN)\",\"description\":\"Sample length.\"},\"LENGTH\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Length (LENGTH)\",\"description\":\"Sample length.\"},\"DETUNE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Detune (DETUNE)\",\"description\":\"Detune with 80 as the centre frequency: first digit steps semitones, second digit 1/16 semitone.\"},\"DEGRADE\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Degrade (DEGRADE)\",\"description\":\"Sample rate reduction; any value above 00 disables sample interpolation.\"}}},\"fmsynth\":{\"name\":\"FM Synth\",\"description\":\"Four-operator, 12-algorithm FM synthesizer. Each operator has a base shape, ratio, level, feedback and two modulation slots.\",\"operatorDestinations\":{\"LEV\":\"controls the level from 00 to the currently set level.\",\"RAT\":\"adds 0.00 to +16.00 to the current ratio.\",\"PIT\":\"adds to the note pitch, in semitones, for this operator.\",\"FBK\":\"controls the feedback from 00 to the currently set feedback.\"},\"params\":{\"ALGO\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Algorithm (ALGO)\",\"description\":\"One of 12 algorithms (oscillator routing); the last one is additive mode.\"},\"A\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Operator A (A)\",\"description\":\"Operator letter with optional shape (SIN, SW2-SW6, SAW, SQU, PUL, IMP, TRI, NOISE, then wave tables).\"},\"B\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Operator B (B)\",\"description\":\"Operator letter with optional shape.\"},\"C\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Operator C (C)\",\"description\":\"Operator letter with optional shape.\"},\"D\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Operator D (D)\",\"description\":\"Operator letter with optional shape.\"},\"RATIO\":{\"type\":\"parameter\",\"format\":\"float\",\"label\":\"Ratio (RATIO)\",\"description\":\"Operator frequency ratio relative to the played note (2.00 is an octave up, 0.50 an octave down).\"},\"LEV/FB\":{\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"level\",\"feedback\"],\"label\":\"Level / Feedback (LEV/FB)\",\"description\":\"Operator volume and feedback.\"},\"MOD\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Modulation Slot (MOD)\",\"description\":\"Assigns one of MOD1-MOD4 to control a destination on the operator.\"},\"LEV\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Level Mod (LEV)\",\"description\":\"Controls the level from 00 to the currently set level.\"},\"RAT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Ratio Mod (RAT)\",\"description\":\"Adds 0.00 to +16.00 to the current ratio.\"},\"PIT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Pitch Mod (PIT)\",\"description\":\"Adds to the note pitch, in semitones, for the operator.\"},\"FBK\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Feedback Mod (FBK)\",\"description\":\"Controls feedback from 00 to the currently set feedback.\"},\"MOD#\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Modulation Source\",\"description\":\"Modulation source value freely assigned to operators through the MOD slots.\"}}},\"hypersynth\":{\"name\":\"Hypersynth\",\"description\":\"Six-note saw wave chord synthesizer with 16 chord banks of up to 6 intervals, detune (swarm), stereo width and a square sub-oscillator.\",\"params\":{\"SCALE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Scale (SCALE)\",\"description\":\"One of the song's scales, or 00 to use the song/track scale settings.\"},\"CHORD\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Chord (CHORD)\",\"description\":\"Chord bank and its intervals (copy with [SHIFT]+[OPTION], paste with [SHIFT]+[EDIT]).\"},\"SHIFT\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Shift (SHIFT)\",\"description\":\"Cross-fades volume between the first 3 intervals and the second 3.\"},\"SHAPE\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Shape (SHAPE)\",\"description\":\"Waveform of the chord oscillators (SAW by default; not in the manual, seen on a Model:02, firmware 6.5).\"},\"SWARM\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Swarm (SWARM)\",\"description\":\"Detunes the oscillators relative to their interval.\"},\"WIDTH\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Stereo Width (WIDTH)\",\"description\":\"Stereo width of the oscillators, from mono 00 to full stereo FF.\"},\"SUBOSC\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"Sub Oscillator (SUBOSC)\",\"description\":\"Mixes in a sub-oscillator 2 octaves below the root (below 80) or 1 octave below (above 80).\"}}},\"external\":{\"name\":\"External Instrument\",\"description\":\"Hybrid MIDI output and audio input device: notes and MIDI FX are sent to the chosen port and channel, audio returns through its filter and amp stage.\",\"params\":{\"INPUT\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"Audio Input (INPUT)\",\"description\":\"Audio input: line-in (stereo, left, right), USB (stereo, left, right), or line-in and USB.\"},\"PORT\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"MIDI Port (PORT)\",\"description\":\"MIDI output port: MIDI and USB, MIDI only, USB only, or Internal (track MIDI input / global MIDI CCs from the MIDI Settings View).\"},\"CHANNEL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"MIDI Channel (CHANNEL)\",\"description\":\"MIDI channel, 1 to 16.\"},\"BANK:PG\":{\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"bank\",\"program\"],\"label\":\"Bank / Program (BANK:PG)\",\"description\":\"Optional MIDI bank select and program change (program change can also be sent as an FX command).\"},\"CC#\":{\"type\":\"parameter\",\"format\":\"text\",\"label\":\"Custom CC (CC:VAL)\",\"description\":\"A custom MIDI CC number, then an optional default value (-- for none), sent with the note-on after program change messages.\"}}},\"midiout\":{\"name\":\"MIDI Out\",\"description\":\"Controls external devices over USB MIDI or the TRS (type A) MIDI output.\",\"params\":{\"PORT\":{\"type\":\"option\",\"format\":\"hexOption\",\"label\":\"MIDI Port (PORT)\",\"description\":\"MIDI output port: MIDI and USB, MIDI only, USB only, or Internal (track MIDI input / global MIDI CCs from the MIDI Settings View).\"},\"CHANNEL\":{\"type\":\"parameter\",\"format\":\"hex\",\"label\":\"MIDI Channel (CHANNEL)\",\"description\":\"MIDI channel, 1 to 16.\"},\"BANK:PG\":{\"type\":\"parameter\",\"format\":\"hexPair\",\"parts\":[\"bank\",\"program\"],\"label\":\"Bank / Program (BANK:PG)\",\"description\":\"Optional MIDI bank select and program change (program change can also be sent as an FX command).\"},\"CC#\":{\"type\":\"parameter\",\"format\":\"text\",\"label\":\"Custom CC (CC:VAL)\",\"description\":\"One of up to 10 custom MIDI CC numbers per instrument, then an optional default value (-- for none), sent with the note-on after program change messages.\"}}}}"),
|
|
3287
3287
|
instrumentTypeNames: {
|
|
3288
3288
|
WAVS: "wavsynth",
|
|
3289
3289
|
MACRO: "macrosynth",
|
|
@@ -3362,8 +3362,67 @@ function qt(e, t, n) {
|
|
|
3362
3362
|
}
|
|
3363
3363
|
return null;
|
|
3364
3364
|
}
|
|
3365
|
-
var Jt = (e) => e.toLowerCase().replace(/[^a-z0-9]+(.)?/g, (e, t) => t ? t.toUpperCase() : "").replace(/^[^a-z]+/, ""), Yt = /^[A-Z][A-Z0-9.:#/ -]
|
|
3366
|
-
|
|
3365
|
+
var Jt = (e) => e.toLowerCase().replace(/[^a-z0-9]+(.)?/g, (e, t) => t ? t.toUpperCase() : "").replace(/^[^a-z]+/, ""), Yt = /^[A-Z][A-Z0-9.:#/ -]*$/, Xt = {
|
|
3366
|
+
RATIO: "ratio",
|
|
3367
|
+
"LEV/FB": "levFb",
|
|
3368
|
+
MOD: "mod"
|
|
3369
|
+
}, Zt = /^(?:-----|[1-4]>[A-Z]{3})$/i;
|
|
3370
|
+
function Qt(e, t, n) {
|
|
3371
|
+
let r = G(t, 0, e.x).trim().toUpperCase(), i = e.letters.map((t, n) => ({
|
|
3372
|
+
letter: t,
|
|
3373
|
+
x: e.x + n * e.step
|
|
3374
|
+
})), a = (e, t, n, i, a) => ({
|
|
3375
|
+
...i,
|
|
3376
|
+
x: t,
|
|
3377
|
+
width: n,
|
|
3378
|
+
key: `${e}${a}`,
|
|
3379
|
+
label: `${i.label} · operator ${a}`,
|
|
3380
|
+
meta: {
|
|
3381
|
+
paramLabel: r || e,
|
|
3382
|
+
operator: a
|
|
3383
|
+
}
|
|
3384
|
+
}), o = Xt[r];
|
|
3385
|
+
if (o) {
|
|
3386
|
+
let t = n.params[r];
|
|
3387
|
+
return t ? i.map(({ letter: i, x: s }) => a(o, s, e.width, r === "MOD" ? $t(t, 1, n) : t, i)) : null;
|
|
3388
|
+
}
|
|
3389
|
+
if (r) return null;
|
|
3390
|
+
if (/^\s+[A-D] \S/i.test(t)) {
|
|
3391
|
+
let r = [];
|
|
3392
|
+
for (let i of t.matchAll(/([A-D]) (\S+)/gi)) {
|
|
3393
|
+
let t = i[1].toUpperCase(), a = n.params[t];
|
|
3394
|
+
a && e.letters.includes(t) && r.push({
|
|
3395
|
+
...a,
|
|
3396
|
+
type: "option",
|
|
3397
|
+
format: "text",
|
|
3398
|
+
x: (i.index ?? 0) + 2,
|
|
3399
|
+
width: i[2].length,
|
|
3400
|
+
key: `shape${t}`,
|
|
3401
|
+
label: `Shape · operator ${t}`,
|
|
3402
|
+
meta: {
|
|
3403
|
+
paramLabel: "SHAPE",
|
|
3404
|
+
operator: t
|
|
3405
|
+
}
|
|
3406
|
+
});
|
|
3407
|
+
}
|
|
3408
|
+
return r.length ? r : null;
|
|
3409
|
+
}
|
|
3410
|
+
let s = i.map(({ x: n }) => G(t, n, e.width).trim()), c = n.params.MOD;
|
|
3411
|
+
return c && s.every((e) => Zt.test(e)) && !G(t, 0, e.x).trim() ? i.map(({ letter: t, x: r }) => a("mod2", r, e.width, $t(c, 2, n), t)) : null;
|
|
3412
|
+
}
|
|
3413
|
+
function $t(e, t, n) {
|
|
3414
|
+
let r = {};
|
|
3415
|
+
for (let [e, t] of Object.entries(n.operatorDestinations ?? {})) for (let n = 1; n <= 4; n += 1) r[`${n}>${e}`] = `MOD${n} ${e}: ${t}`;
|
|
3416
|
+
return {
|
|
3417
|
+
...e,
|
|
3418
|
+
type: "option",
|
|
3419
|
+
format: "text",
|
|
3420
|
+
label: `Modulation Slot ${t} (MOD)`,
|
|
3421
|
+
options: r
|
|
3422
|
+
};
|
|
3423
|
+
}
|
|
3424
|
+
var en = /^(CC[A-J])(?: CC:VAL)? +(?=\S)/i, tn = 6;
|
|
3425
|
+
function nn(e, t, n) {
|
|
3367
3426
|
if (e.kind === "browser") {
|
|
3368
3427
|
let r = n.entryText?.trim() || t.trim();
|
|
3369
3428
|
return r ? {
|
|
@@ -3405,24 +3464,31 @@ function Xt(e, t, n) {
|
|
|
3405
3464
|
rowId: r.id,
|
|
3406
3465
|
cells: r.cells
|
|
3407
3466
|
};
|
|
3467
|
+
if (e.operators && n.instrumentKey === e.operators.instrument) {
|
|
3468
|
+
let n = Qt(e.operators, t, Lt[e.operators.instrument]);
|
|
3469
|
+
if (n) return {
|
|
3470
|
+
rowId: "operators",
|
|
3471
|
+
cells: n
|
|
3472
|
+
};
|
|
3473
|
+
}
|
|
3408
3474
|
let r = e.zones ?? [], i = [];
|
|
3409
3475
|
return r.forEach((a, o) => {
|
|
3410
|
-
let s = G(t, a.labelX, a.labelWidth).trim().toUpperCase();
|
|
3411
|
-
if (!Yt.test(s)) return;
|
|
3412
|
-
let
|
|
3413
|
-
if (!G(t,
|
|
3414
|
-
let
|
|
3476
|
+
let s = G(t, a.labelX, a.labelWidth).trim().toUpperCase(), c = a.x, l = null, u = o === 0 ? en.exec(t) : null;
|
|
3477
|
+
if (u && (s = u[1].toUpperCase(), c = u[0].length, l = tn), !Yt.test(s)) return;
|
|
3478
|
+
let d = r[o + 1], f = d != null && G(t, d.labelX - 1, 1).trim() === "" && Yt.test(G(t, d.labelX, d.labelWidth).trim().toUpperCase()), p = l ?? (d && f ? Math.max(1, d.labelX - 1 - c) : a.width);
|
|
3479
|
+
if (!G(t, c, p).trim()) return;
|
|
3480
|
+
let m = qt(e, s, n.instrumentKey), h = Jt(s) || a.id, g = i.some((e) => e.key === h) ? `${h}${a.id[0].toUpperCase()}${a.id.slice(1)}` : h;
|
|
3415
3481
|
i.push({
|
|
3416
|
-
x:
|
|
3417
|
-
width:
|
|
3418
|
-
key:
|
|
3419
|
-
type:
|
|
3420
|
-
format:
|
|
3421
|
-
label:
|
|
3422
|
-
description:
|
|
3423
|
-
parts:
|
|
3424
|
-
options:
|
|
3425
|
-
unit:
|
|
3482
|
+
x: c,
|
|
3483
|
+
width: p,
|
|
3484
|
+
key: g,
|
|
3485
|
+
type: m?.type ?? "parameter",
|
|
3486
|
+
format: m?.format ?? "auto",
|
|
3487
|
+
label: m?.label ?? s,
|
|
3488
|
+
description: m?.description,
|
|
3489
|
+
parts: m?.parts,
|
|
3490
|
+
options: m?.options,
|
|
3491
|
+
unit: m?.unit,
|
|
3426
3492
|
meta: {
|
|
3427
3493
|
paramLabel: s,
|
|
3428
3494
|
zone: a.id
|
|
@@ -3439,13 +3505,13 @@ var K = {
|
|
|
3439
3505
|
values: null,
|
|
3440
3506
|
text: null
|
|
3441
3507
|
};
|
|
3442
|
-
function
|
|
3508
|
+
function rn(e) {
|
|
3443
3509
|
return /^[0-9A-F]{2}$/i.test(e) ? "hex" : /^[0-9A-F]{2}:[0-9A-F]{2}$/i.test(e) ? "hexPair" : /^[+-]?\d+([.,]\d+)?$/.test(e) ? "float" : /^[0-9A-F]{2}\S/i.test(e) ? "hexOption" : "text";
|
|
3444
3510
|
}
|
|
3445
|
-
function
|
|
3511
|
+
function an(e, t) {
|
|
3446
3512
|
let n = e.trim();
|
|
3447
3513
|
if (!n) return K;
|
|
3448
|
-
switch (t === "auto" ?
|
|
3514
|
+
switch (t === "auto" ? rn(n) : t) {
|
|
3449
3515
|
case "hex": {
|
|
3450
3516
|
let e = /^([0-9A-F]{2})/i.exec(n), t = e ? parseInt(e[1], 16) : null;
|
|
3451
3517
|
return {
|
|
@@ -3470,7 +3536,7 @@ function Qt(e, t) {
|
|
|
3470
3536
|
};
|
|
3471
3537
|
}
|
|
3472
3538
|
case "hexPair": {
|
|
3473
|
-
let e = /^([0-9A-F]{2})
|
|
3539
|
+
let e = /^([0-9A-F]{2})[:/]([0-9A-F]{2})/i.exec(n);
|
|
3474
3540
|
if (!e) return {
|
|
3475
3541
|
...K,
|
|
3476
3542
|
text: n
|
|
@@ -3527,7 +3593,7 @@ function Qt(e, t) {
|
|
|
3527
3593
|
};
|
|
3528
3594
|
}
|
|
3529
3595
|
}
|
|
3530
|
-
function
|
|
3596
|
+
function on(e, t) {
|
|
3531
3597
|
if (!e || !t) return null;
|
|
3532
3598
|
let n = t.toUpperCase().trim();
|
|
3533
3599
|
if (e[n]) return e[n];
|
|
@@ -3536,28 +3602,28 @@ function $t(e, t) {
|
|
|
3536
3602
|
}
|
|
3537
3603
|
//#endregion
|
|
3538
3604
|
//#region src/fxCommands.ts
|
|
3539
|
-
var
|
|
3540
|
-
function
|
|
3541
|
-
let t =
|
|
3542
|
-
return t.length === 0 || t.length ===
|
|
3605
|
+
var sn = W.fxCommands, cn = W.instrumentFx.types, ln = Object.entries(cn).filter(([, e]) => e.verified).map(([e]) => e);
|
|
3606
|
+
function un(e) {
|
|
3607
|
+
let t = ln.filter((t) => cn[t].commands.includes(e));
|
|
3608
|
+
return t.length === 0 || t.length === ln.length ? null : t;
|
|
3543
3609
|
}
|
|
3544
|
-
function
|
|
3610
|
+
function dn(e) {
|
|
3545
3611
|
let t = e.toUpperCase();
|
|
3546
3612
|
for (let e of [
|
|
3547
3613
|
"sequencer",
|
|
3548
3614
|
"instrument",
|
|
3549
3615
|
"mixer"
|
|
3550
3616
|
]) {
|
|
3551
|
-
let n =
|
|
3617
|
+
let n = sn[e][t];
|
|
3552
3618
|
if (n) return {
|
|
3553
3619
|
description: n.description,
|
|
3554
3620
|
category: e,
|
|
3555
3621
|
relative: n.relative === !0,
|
|
3556
|
-
instrumentTypes: e === "instrument" ?
|
|
3622
|
+
instrumentTypes: e === "instrument" ? un(t) : null,
|
|
3557
3623
|
slot: null
|
|
3558
3624
|
};
|
|
3559
3625
|
}
|
|
3560
|
-
let n = /^([A-Z]{2})([1-4])$/.exec(t), r = n ?
|
|
3626
|
+
let n = /^([A-Z]{2})([1-4])$/.exec(t), r = n ? sn.modulation[n[1]] : void 0;
|
|
3561
3627
|
if (n && r) return {
|
|
3562
3628
|
description: r.description.replace("modulator N", `modulator ${n[2]}`),
|
|
3563
3629
|
category: "modulation",
|
|
@@ -3567,24 +3633,24 @@ function an(e) {
|
|
|
3567
3633
|
};
|
|
3568
3634
|
}
|
|
3569
3635
|
function q(e) {
|
|
3570
|
-
return
|
|
3636
|
+
return dn(e)?.relative === !0;
|
|
3571
3637
|
}
|
|
3572
|
-
function
|
|
3573
|
-
let t =
|
|
3638
|
+
function fn(e) {
|
|
3639
|
+
let t = cn[e.toLowerCase()];
|
|
3574
3640
|
return t ? {
|
|
3575
3641
|
type: e.toLowerCase(),
|
|
3576
3642
|
verified: t.verified,
|
|
3577
3643
|
commands: [...t.commands]
|
|
3578
3644
|
} : null;
|
|
3579
3645
|
}
|
|
3580
|
-
var
|
|
3581
|
-
function
|
|
3646
|
+
var pn = W.instrumentFx.relativeCommands.description, J = (e) => e.toString(16).toUpperCase().padStart(2, "0"), Y = (e) => e.toString(16).toUpperCase(), mn = (e) => e === 1 ? "once" : e === 2 ? "twice" : `${e} times`, X = (e) => e > 127 ? e - 256 : e, hn = (e) => `${e > 0 ? "+" : e < 0 ? "−" : "±"}${Math.abs(e)}`;
|
|
3647
|
+
function gn(e, t) {
|
|
3582
3648
|
return q(e) && t > 127 ? `${J(t)} (${X(t)})` : J(t);
|
|
3583
3649
|
}
|
|
3584
|
-
function
|
|
3650
|
+
function _n(e) {
|
|
3585
3651
|
return e > 127 ? `−${J(256 - e)}` : `+${J(e)}`;
|
|
3586
3652
|
}
|
|
3587
|
-
var
|
|
3653
|
+
var vn = [
|
|
3588
3654
|
"C-",
|
|
3589
3655
|
"C#",
|
|
3590
3656
|
"D-",
|
|
@@ -3598,16 +3664,16 @@ var fn = [
|
|
|
3598
3664
|
"A#",
|
|
3599
3665
|
"B-"
|
|
3600
3666
|
];
|
|
3601
|
-
function
|
|
3667
|
+
function yn(e) {
|
|
3602
3668
|
let t = /^([A-G])([#-])(\d)$/.exec((e ?? "").trim().toUpperCase());
|
|
3603
3669
|
if (!t) return null;
|
|
3604
|
-
let n =
|
|
3670
|
+
let n = vn.indexOf(`${t[1]}${t[2]}`);
|
|
3605
3671
|
return n < 0 ? null : Number(t[3]) * 12 + n;
|
|
3606
3672
|
}
|
|
3607
|
-
function
|
|
3608
|
-
return `${
|
|
3673
|
+
function bn(e) {
|
|
3674
|
+
return `${vn[(e % 12 + 12) % 12]}${Math.floor(e / 12)}`;
|
|
3609
3675
|
}
|
|
3610
|
-
var
|
|
3676
|
+
var xn = [
|
|
3611
3677
|
"C",
|
|
3612
3678
|
"C#",
|
|
3613
3679
|
"D",
|
|
@@ -3620,14 +3686,14 @@ var hn = [
|
|
|
3620
3686
|
"A",
|
|
3621
3687
|
"A#",
|
|
3622
3688
|
"B"
|
|
3623
|
-
],
|
|
3624
|
-
function
|
|
3625
|
-
return e ===
|
|
3689
|
+
], Sn = 6;
|
|
3690
|
+
function Cn(e) {
|
|
3691
|
+
return e === Sn ? "one row per step" : Sn % e === 0 ? `${Sn / e} rows per step` : e % Sn === 0 ? `one row every ${e / Sn} steps` : "";
|
|
3626
3692
|
}
|
|
3627
|
-
function
|
|
3693
|
+
function wn(e, t) {
|
|
3628
3694
|
if (e === 0) return `${t} moves one row each time the instrument is triggered`;
|
|
3629
3695
|
if (e <= 251) {
|
|
3630
|
-
let n =
|
|
3696
|
+
let n = Cn(e);
|
|
3631
3697
|
return `${t} moves one row every ${e} tick${e === 1 ? "" : "s"}${n ? ` (${n})` : ""}`;
|
|
3632
3698
|
}
|
|
3633
3699
|
return [
|
|
@@ -3637,12 +3703,12 @@ function vn(e, t) {
|
|
|
3637
3703
|
`${t} moves one row every 5 ms (200 Hz)`
|
|
3638
3704
|
][e - 252] ?? null;
|
|
3639
3705
|
}
|
|
3640
|
-
function
|
|
3706
|
+
function Tn(e, t, n = {}) {
|
|
3641
3707
|
let r = e.toUpperCase(), i = t >> 4, a = t & 15, o = (e) => `${e} tick${e === 1 ? "" : "s"}`;
|
|
3642
3708
|
switch (r) {
|
|
3643
3709
|
case "ARP": {
|
|
3644
|
-
let e =
|
|
3645
|
-
return e == null ? `plays the note, then ${t}` : `${t}: ${
|
|
3710
|
+
let e = yn(n.note), t = `+${i} and +${a} semitones`;
|
|
3711
|
+
return e == null ? `plays the note, then ${t}` : `${t}: ${bn(e)} ${bn(e + i)} ${bn(e + a)}`;
|
|
3646
3712
|
}
|
|
3647
3713
|
case "ARC": return `arp mode ${i}, speed ${o(a)}`;
|
|
3648
3714
|
case "CHA": return n.inTable ? `everything left of it plays with probability ${t}/255 (00 never, FF always)` : `${i}/15 chance for what is left of it, ${a}/15 for what is right (0 never, F always)`;
|
|
@@ -3656,7 +3722,7 @@ function yn(e, t, n = {}) {
|
|
|
3656
3722
|
case "TBL": return `instrument uses table ${J(t)}`;
|
|
3657
3723
|
case "TBX": return t === 0 ? "stops the auxiliary table" : `plays table ${J(t)} alongside the instrument table`;
|
|
3658
3724
|
case "THO": return n.inTable ? `every column of the table jumps to row ${Y(a)}` : `the instrument's table jumps to row ${Y(a)} (the aux table when a TBX is on this step)`;
|
|
3659
|
-
case "HOP": return n.inTable ? a === n.row ? i === 0 ? `this column stops on row ${Y(a)}` : `holds this column on row ${Y(a)} ${
|
|
3725
|
+
case "HOP": return n.inTable ? a === n.row ? i === 0 ? `this column stops on row ${Y(a)}` : `holds this column on row ${Y(a)} ${mn(i)}` : i === 0 ? `always jumps back to row ${Y(a)}: the rows in between loop` : `jumps to row ${Y(a)} ${mn(i)}, then the column runs on past it` : t === 255 ? "stops this track" : `jumps to row ${Y(a)} of the next phrase`;
|
|
3660
3726
|
case "REP": return !n.inTable || t === 0 ? null : `plays the command above it ${t} more time${t === 1 ? "" : "s"}, one row each`;
|
|
3661
3727
|
case "RTO": return n.inTable ? `repeats the relative command above it until it has added ${t > 127 ? `${J(t)} (${X(t)})` : J(t)} in total` : null;
|
|
3662
3728
|
case "RMX": return `tracks to its left (selection ${Y(i)}) jump to phrase row ${Y(a)}`;
|
|
@@ -3668,47 +3734,47 @@ function yn(e, t, n = {}) {
|
|
|
3668
3734
|
case "PBN": return t < 128 ? `pitch slides up by ${t}` : `pitch slides down by ${256 - t}`;
|
|
3669
3735
|
case "SCA":
|
|
3670
3736
|
case "SCG": {
|
|
3671
|
-
let e =
|
|
3737
|
+
let e = xn[i];
|
|
3672
3738
|
return `${r === "SCA" ? "track" : "song"} scale ${a.toString(16).toUpperCase()}${e ? `, key ${e}` : ""}`;
|
|
3673
3739
|
}
|
|
3674
|
-
case "SNG": return `moves the song position by ${
|
|
3740
|
+
case "SNG": return `moves the song position by ${hn(X(t))} row(s)`;
|
|
3675
3741
|
case "SED": return `random seed ${J(t)}`;
|
|
3676
3742
|
case "NXT": return `plays instrument ${J(t)} on the next track`;
|
|
3677
3743
|
case "MTT": {
|
|
3678
3744
|
if (n.inTable) return "no effect in a table";
|
|
3679
3745
|
let e = X(t);
|
|
3680
|
-
return e < 0 && n.row === 0 ? "no effect: a row cannot be moved earlier on the first step" : e === 0 ? "no timing shift" : `shifts the row by ${
|
|
3746
|
+
return e < 0 && n.row === 0 ? "no effect: a row cannot be moved earlier on the first step" : e === 0 ? "no timing shift" : `shifts the row by ${hn(e)}/8 tick`;
|
|
3681
3747
|
}
|
|
3682
3748
|
case "TPO": return `${t} BPM`;
|
|
3683
|
-
case "TSP": return `transposes the song by ${
|
|
3684
|
-
case "TIC": return
|
|
3749
|
+
case "TSP": return `transposes the song by ${hn(X(t))} semitones`;
|
|
3750
|
+
case "TIC": return wn(t, n.inTable ? "this column" : "the instrument's table");
|
|
3685
3751
|
case "XRZ": return t > 0 ? "reverb freeze on" : "reverb freeze off";
|
|
3686
3752
|
}
|
|
3687
3753
|
if (q(r)) {
|
|
3688
3754
|
let e = X(t);
|
|
3689
|
-
return r === "PIT" ? e === 0 ? "no change" : `${
|
|
3755
|
+
return r === "PIT" ? e === 0 ? "no change" : `${hn(e)} semitones` : e === 0 ? "no change" : hn(e);
|
|
3690
3756
|
}
|
|
3691
3757
|
return null;
|
|
3692
3758
|
}
|
|
3693
|
-
function
|
|
3759
|
+
function En(e, t, n) {
|
|
3694
3760
|
let r = e + t & 255;
|
|
3695
3761
|
return n != null && (t < 128 ? r < e || r > n : r > e || r < n) && (r = n), {
|
|
3696
3762
|
value: r,
|
|
3697
3763
|
atLimit: n != null && r === n
|
|
3698
3764
|
};
|
|
3699
3765
|
}
|
|
3700
|
-
function
|
|
3766
|
+
function Dn(e, t, n, r = !1) {
|
|
3701
3767
|
let i = null, a = null, o = null, s = null, c = r, l = !1, u = null, d = "none", f = Math.min(n, e.length - 1);
|
|
3702
3768
|
for (let n = 0; n <= f; n += 1) {
|
|
3703
3769
|
let f = e[n].fields[`fx${t}cmd`], p = e[n].fields[`fx${t}val`];
|
|
3704
3770
|
if (d = "none", f && !f.isEmpty) {
|
|
3705
3771
|
let e = f.rawValue.toUpperCase(), t = p && !p.isEmpty ? p.hexValue : null;
|
|
3706
|
-
e === "REP" ? t ? !i && !r ? d = "orphan" : (d = c ? "repChange" : "rep", c || (u = n), c = !0, o = t, a != null && ({value: a, atLimit: l} =
|
|
3772
|
+
e === "REP" ? t ? !i && !r ? d = "orphan" : (d = c ? "repChange" : "rep", c || (u = n), c = !0, o = t, a != null && ({value: a, atLimit: l} = En(a, o, s))) : (d = "repStop", c = !1, o = null, l = !1) : e === "RTO" ? (d = "rto", s = t) : (d = c ? "replace" : "set", i = {
|
|
3707
3773
|
cmd: e,
|
|
3708
3774
|
value: t,
|
|
3709
3775
|
step: n
|
|
3710
3776
|
}, a = t, c = !1, o = null, s = null, l = !1, u = null);
|
|
3711
|
-
} else c && (d = "continue", a != null && o != null && ({value: a, atLimit: l} =
|
|
3777
|
+
} else c && (d = "continue", a != null && o != null && ({value: a, atLimit: l} = En(a, o, s)));
|
|
3712
3778
|
}
|
|
3713
3779
|
return {
|
|
3714
3780
|
lane: t,
|
|
@@ -3724,8 +3790,8 @@ function xn(e, t, n, r = !1) {
|
|
|
3724
3790
|
carried: c && !i
|
|
3725
3791
|
};
|
|
3726
3792
|
}
|
|
3727
|
-
function
|
|
3728
|
-
let t = e.source, n = (e) => e == null ? "??" : t ?
|
|
3793
|
+
function On(e) {
|
|
3794
|
+
let t = e.source, n = (e) => e == null ? "??" : t ? gn(t.cmd, e) : J(e), r = e.increment == null ? "" : _n(e.increment), i = e.atLimit && e.limit != null ? `, held at the RTO limit ${J(e.limit)}` : "";
|
|
3729
3795
|
switch (e.event) {
|
|
3730
3796
|
case "rep":
|
|
3731
3797
|
case "repChange": return e.carried ? `REP ${r} per step continues the repeat from the previous phrase` : `${e.event === "rep" ? "repeats" : "now repeats"} ${t?.cmd} from ${n(t?.value ?? null)} (step ${t?.step.toString(16).toUpperCase()}), ${r} per step → ${n(e.value)} on this step${i}`;
|
|
@@ -3737,7 +3803,7 @@ function Sn(e) {
|
|
|
3737
3803
|
default: return null;
|
|
3738
3804
|
}
|
|
3739
3805
|
}
|
|
3740
|
-
function
|
|
3806
|
+
function kn(e) {
|
|
3741
3807
|
let t = e.fields.inst;
|
|
3742
3808
|
return t && !t.isEmpty ? "instrument" : [
|
|
3743
3809
|
1,
|
|
@@ -3748,10 +3814,10 @@ function Cn(e) {
|
|
|
3748
3814
|
return n != null && !n.isEmpty && n.rawValue.toUpperCase() === "RET";
|
|
3749
3815
|
}) ? "ret" : null;
|
|
3750
3816
|
}
|
|
3751
|
-
function
|
|
3817
|
+
function An(e, t, n = null) {
|
|
3752
3818
|
let r = {}, i = null, a = null, o = Math.min(t, e.length - 1);
|
|
3753
3819
|
for (let t = 0; t <= o; t += 1) {
|
|
3754
|
-
let o =
|
|
3820
|
+
let o = kn(e[t]);
|
|
3755
3821
|
if (o) {
|
|
3756
3822
|
for (let e of Object.keys(r)) delete r[e];
|
|
3757
3823
|
i = t, a = o;
|
|
@@ -3761,7 +3827,7 @@ function wn(e, t, n = null) {
|
|
|
3761
3827
|
2,
|
|
3762
3828
|
3
|
|
3763
3829
|
]) {
|
|
3764
|
-
let s =
|
|
3830
|
+
let s = Dn(e, o, t, n === o), c = s.source;
|
|
3765
3831
|
if (!c || s.carried || !q(c.cmd)) continue;
|
|
3766
3832
|
let l = null, u = !1;
|
|
3767
3833
|
if (s.event === "set" || s.event === "replace" ? l = c.value : (s.event === "rep" || s.event === "repChange" || s.event === "continue") && (l = s.value, u = !0), l == null) continue;
|
|
@@ -3778,21 +3844,21 @@ function wn(e, t, n = null) {
|
|
|
3778
3844
|
}
|
|
3779
3845
|
return r;
|
|
3780
3846
|
}
|
|
3781
|
-
var
|
|
3782
|
-
function
|
|
3847
|
+
var jn = (e) => e === 0 ? "±00" : `${e > 0 ? "+" : "−"}${J(Math.abs(e))}`;
|
|
3848
|
+
function Mn(e) {
|
|
3783
3849
|
if (e.resetStep == null) return "the start of this phrase (earlier state unknown)";
|
|
3784
3850
|
let t = e.resetStep.toString(16).toUpperCase();
|
|
3785
3851
|
return e.resetBy === "ret" ? `the RET on step ${t}` : `the instrument number on step ${t}`;
|
|
3786
3852
|
}
|
|
3787
|
-
var
|
|
3788
|
-
function
|
|
3789
|
-
if (!e || e.count <= 1) return `relative: ${
|
|
3790
|
-
let t = e.viaRep ? ", including REP repeats" : "", n = e.total === 0 ? "has had no net effect" : `has moved by ${
|
|
3791
|
-
return `relative: ${e.cmd} ${n} over ${e.count} steps since ${
|
|
3853
|
+
var Nn = "stays until a note with an instrument number (I) or a RET resets it";
|
|
3854
|
+
function Pn(e) {
|
|
3855
|
+
if (!e || e.count <= 1) return `relative: ${Nn}`;
|
|
3856
|
+
let t = e.viaRep ? ", including REP repeats" : "", n = e.total === 0 ? "has had no net effect" : `has moved by ${jn(e.total)}`;
|
|
3857
|
+
return `relative: ${e.cmd} ${n} over ${e.count} steps since ${Mn(e)}${t}; ${Nn}`;
|
|
3792
3858
|
}
|
|
3793
|
-
function
|
|
3859
|
+
function Fn(e) {
|
|
3794
3860
|
let t = Object.values(e).filter((e) => e.total !== 0);
|
|
3795
|
-
return t.length ? `triggers the instrument again: resets the relative changes still in force (${t.map((e) => `${e.cmd} ${
|
|
3861
|
+
return t.length ? `triggers the instrument again: resets the relative changes still in force (${t.map((e) => `${e.cmd} ${jn(e.total)}`).join(", ")})` : null;
|
|
3796
3862
|
}
|
|
3797
3863
|
//#endregion
|
|
3798
3864
|
//#region src/scaleInsight.ts
|
|
@@ -3809,7 +3875,7 @@ var Z = [
|
|
|
3809
3875
|
"A",
|
|
3810
3876
|
"A#",
|
|
3811
3877
|
"B"
|
|
3812
|
-
],
|
|
3878
|
+
], In = [
|
|
3813
3879
|
{
|
|
3814
3880
|
name: "Major (Ionian)",
|
|
3815
3881
|
steps: [
|
|
@@ -4027,7 +4093,7 @@ var Z = [
|
|
|
4027
4093
|
11
|
|
4028
4094
|
]
|
|
4029
4095
|
}
|
|
4030
|
-
],
|
|
4096
|
+
], Ln = [
|
|
4031
4097
|
"the root",
|
|
4032
4098
|
"a minor 2nd",
|
|
4033
4099
|
"a major 2nd",
|
|
@@ -4041,26 +4107,26 @@ var Z = [
|
|
|
4041
4107
|
"a minor 7th",
|
|
4042
4108
|
"a major 7th"
|
|
4043
4109
|
];
|
|
4044
|
-
function
|
|
4110
|
+
function Rn(e) {
|
|
4045
4111
|
let t = e.replace(/[-\s]/g, "").toUpperCase();
|
|
4046
4112
|
return Z.includes(t) ? t : null;
|
|
4047
4113
|
}
|
|
4048
|
-
function
|
|
4114
|
+
function zn(e) {
|
|
4049
4115
|
let t = Z.indexOf(e);
|
|
4050
|
-
return t <= 0 ? t === 0 ? "the first row (the scale root)" : e : `${
|
|
4116
|
+
return t <= 0 ? t === 0 ? "the first row (the scale root)" : e : `${Ln[t]} (+${t} semitones above C)`;
|
|
4051
4117
|
}
|
|
4052
|
-
function
|
|
4118
|
+
function Bn(e) {
|
|
4053
4119
|
let t = new Set(e);
|
|
4054
4120
|
if (t.size === 0) return [];
|
|
4055
4121
|
let n = [];
|
|
4056
|
-
for (let e of
|
|
4122
|
+
for (let e of In) if (e.steps.length === t.size) for (let r = 0; r < 12; r += 1) e.steps.every((e) => t.has((e + r) % 12)) && n.push({
|
|
4057
4123
|
root: r,
|
|
4058
4124
|
name: e.name
|
|
4059
4125
|
});
|
|
4060
4126
|
return n.sort((e, t) => e.root - t.root), n.map((e) => e.root === 0 ? e.name : `${e.name} from ${Z[e.root]}`);
|
|
4061
4127
|
}
|
|
4062
|
-
function
|
|
4063
|
-
let t = e.filter((e) => e.enabled === !0), n = t.map((e) => e.interval), r =
|
|
4128
|
+
function Vn(e) {
|
|
4129
|
+
let t = e.filter((e) => e.enabled === !0), n = t.map((e) => e.interval), r = Bn(t.map((e) => e.semitone)), i = e.filter((e) => e.enabled === !0 && e.offset != null && e.offset !== 0).map((e) => ({
|
|
4064
4130
|
interval: e.interval,
|
|
4065
4131
|
offset: e.offset
|
|
4066
4132
|
}));
|
|
@@ -4069,47 +4135,47 @@ function Fn(e) {
|
|
|
4069
4135
|
enabled: n,
|
|
4070
4136
|
shapes: r,
|
|
4071
4137
|
detuned: i,
|
|
4072
|
-
summary:
|
|
4138
|
+
summary: Hn({
|
|
4073
4139
|
enabled: n,
|
|
4074
4140
|
shapes: r,
|
|
4075
4141
|
detuned: i
|
|
4076
4142
|
}).join(" — ")
|
|
4077
4143
|
};
|
|
4078
4144
|
}
|
|
4079
|
-
function
|
|
4145
|
+
function Hn(e) {
|
|
4080
4146
|
let { enabled: t, shapes: n, detuned: r } = e;
|
|
4081
4147
|
if (!t.length) return ["no notes enabled"];
|
|
4082
4148
|
let i = n[0] ?? `${t.length} notes, custom scale`;
|
|
4083
|
-
return r.length && (i += `; detuned: ${r.map((e) => `${e.interval} ${
|
|
4149
|
+
return r.length && (i += `; detuned: ${r.map((e) => `${e.interval} ${Un(e.offset)}`).join(", ")}`), [t.join(" "), i];
|
|
4084
4150
|
}
|
|
4085
|
-
function
|
|
4151
|
+
function Un(e) {
|
|
4086
4152
|
return `${e > 0 ? "+" : e < 0 ? "−" : ""}${Math.abs(e).toFixed(2)} st`;
|
|
4087
4153
|
}
|
|
4088
4154
|
//#endregion
|
|
4089
4155
|
//#region src/viewContext.ts
|
|
4090
|
-
var
|
|
4156
|
+
var Wn = /* @__PURE__ */ new Set([
|
|
4091
4157
|
"--",
|
|
4092
4158
|
"---",
|
|
4093
4159
|
"---00",
|
|
4094
4160
|
"----",
|
|
4095
4161
|
"-"
|
|
4096
4162
|
]);
|
|
4097
|
-
function
|
|
4098
|
-
return !e ||
|
|
4163
|
+
function Gn(e) {
|
|
4164
|
+
return !e || Wn.has(e) || /^-+$/.test(e);
|
|
4099
4165
|
}
|
|
4100
|
-
function
|
|
4166
|
+
function Kn(e) {
|
|
4101
4167
|
let t = e.trim();
|
|
4102
|
-
if (!t ||
|
|
4168
|
+
if (!t || Gn(t)) return null;
|
|
4103
4169
|
let n = parseInt(t, 16);
|
|
4104
4170
|
return Number.isNaN(n) ? null : n;
|
|
4105
4171
|
}
|
|
4106
|
-
function
|
|
4172
|
+
function qn(e, t, n) {
|
|
4107
4173
|
return t >= e.length ? "" : e.slice(t, Math.min(t + n, e.length));
|
|
4108
4174
|
}
|
|
4109
|
-
function
|
|
4110
|
-
return
|
|
4175
|
+
function Jn(e) {
|
|
4176
|
+
return Yn(e);
|
|
4111
4177
|
}
|
|
4112
|
-
function
|
|
4178
|
+
function Yn(e) {
|
|
4113
4179
|
if (!e) return {
|
|
4114
4180
|
viewId: null,
|
|
4115
4181
|
isUnsaved: !1,
|
|
@@ -4122,7 +4188,7 @@ function Un(e) {
|
|
|
4122
4188
|
marker: r
|
|
4123
4189
|
};
|
|
4124
4190
|
}
|
|
4125
|
-
function
|
|
4191
|
+
function Xn(e) {
|
|
4126
4192
|
return e.length > 0 && /^[^a-zA-Z0-9 ]/.test(e[0]) ? {
|
|
4127
4193
|
line: e.slice(1),
|
|
4128
4194
|
offset: 1
|
|
@@ -4131,12 +4197,12 @@ function Wn(e) {
|
|
|
4131
4197
|
offset: 0
|
|
4132
4198
|
};
|
|
4133
4199
|
}
|
|
4134
|
-
function
|
|
4135
|
-
let n =
|
|
4200
|
+
function Zn(e, t) {
|
|
4201
|
+
let n = qn(t, e.x, e.width).trim();
|
|
4136
4202
|
n.includes("^") && (e.type === "fxCommand" || e.type === "fxValue") && (n = "");
|
|
4137
|
-
let r =
|
|
4203
|
+
let r = Gn(n);
|
|
4138
4204
|
if (e.format) {
|
|
4139
|
-
let t = r ? null :
|
|
4205
|
+
let t = r ? null : an(n, e.format), i = e.type === "name" || e.type === "fileEntry", a = t?.text != null && !i ? t.text.toUpperCase() : t?.text ?? null;
|
|
4140
4206
|
return {
|
|
4141
4207
|
key: e.key,
|
|
4142
4208
|
label: e.label,
|
|
@@ -4151,8 +4217,8 @@ function Gn(e, t) {
|
|
|
4151
4217
|
values: t?.values ?? null,
|
|
4152
4218
|
parts: e.parts,
|
|
4153
4219
|
unit: e.unit,
|
|
4154
|
-
valueDescription: !r &&
|
|
4155
|
-
fileKind: e.type === "fileEntry" ?
|
|
4220
|
+
valueDescription: !r && on(e.options, a ?? n) || void 0,
|
|
4221
|
+
fileKind: e.type === "fileEntry" ? Qn(n) : void 0
|
|
4156
4222
|
};
|
|
4157
4223
|
}
|
|
4158
4224
|
let i = [
|
|
@@ -4172,7 +4238,7 @@ function Gn(e, t) {
|
|
|
4172
4238
|
if (a.includes(e.type)) {
|
|
4173
4239
|
let e = parseInt(n, 10);
|
|
4174
4240
|
o = Number.isNaN(e) ? null : e;
|
|
4175
|
-
} else o =
|
|
4241
|
+
} else o = Kn(n);
|
|
4176
4242
|
}
|
|
4177
4243
|
return {
|
|
4178
4244
|
key: e.key,
|
|
@@ -4184,20 +4250,20 @@ function Gn(e, t) {
|
|
|
4184
4250
|
meta: e.meta
|
|
4185
4251
|
};
|
|
4186
4252
|
}
|
|
4187
|
-
function
|
|
4253
|
+
function Qn(e) {
|
|
4188
4254
|
if (e === "/..") return "parent";
|
|
4189
4255
|
if (e.startsWith("/")) return "directory";
|
|
4190
4256
|
let t = /\.([a-z0-9]+)$/i.exec(e)?.[1]?.toLowerCase();
|
|
4191
4257
|
return t === "m8i" ? "instrumentPreset" : t === "wav" ? "sample" : t?.startsWith("m8") ? "m8file" : "file";
|
|
4192
4258
|
}
|
|
4193
|
-
function
|
|
4194
|
-
let n =
|
|
4259
|
+
function $n(e, t) {
|
|
4260
|
+
let n = qn(e, t.x, t.width).trim();
|
|
4195
4261
|
if (!n) return null;
|
|
4196
|
-
if (t.parse === "hex") return
|
|
4262
|
+
if (t.parse === "hex") return Kn(n);
|
|
4197
4263
|
let r = parseInt(n, 10);
|
|
4198
4264
|
return Number.isNaN(r) ? null : r;
|
|
4199
4265
|
}
|
|
4200
|
-
function
|
|
4266
|
+
function er(e, t) {
|
|
4201
4267
|
for (let n of e) if (t >= n.x && t < n.x + n.width) return n;
|
|
4202
4268
|
let n = null, r = 2;
|
|
4203
4269
|
for (let i of e) {
|
|
@@ -4206,9 +4272,9 @@ function Jn(e, t) {
|
|
|
4206
4272
|
}
|
|
4207
4273
|
return n;
|
|
4208
4274
|
}
|
|
4209
|
-
function
|
|
4275
|
+
function tr(e, t) {
|
|
4210
4276
|
let n = {};
|
|
4211
|
-
for (let r of e.columns ?? []) n[r.key] =
|
|
4277
|
+
for (let r of e.columns ?? []) n[r.key] = Zn(r, t);
|
|
4212
4278
|
for (let e of Object.keys(n)) {
|
|
4213
4279
|
let t = /^fx(\d)cmd$/.exec(e)?.[1], r = t ? n[`fx${t}val`] : void 0;
|
|
4214
4280
|
r && n[e].isEmpty && (n[`fx${t}val`] = {
|
|
@@ -4217,27 +4283,27 @@ function Yn(e, t) {
|
|
|
4217
4283
|
});
|
|
4218
4284
|
}
|
|
4219
4285
|
return {
|
|
4220
|
-
rowIndex: e.rowField ?
|
|
4286
|
+
rowIndex: e.rowField ? $n(t, e.rowField) : null,
|
|
4221
4287
|
rowKey: e.rowField?.key ?? "row",
|
|
4222
4288
|
rowId: null,
|
|
4223
4289
|
fields: n
|
|
4224
4290
|
};
|
|
4225
4291
|
}
|
|
4226
|
-
var
|
|
4227
|
-
function
|
|
4292
|
+
var nr = (e) => e.replace(/\s+/g, ""), rr = 1, Q = (e) => e.slice(1);
|
|
4293
|
+
function ir(e, t) {
|
|
4228
4294
|
if (!t || !e.cursorPos || !e.currentLine) return !1;
|
|
4229
4295
|
let n = t.lines[e.cursorPos.y];
|
|
4230
|
-
return n != null &&
|
|
4296
|
+
return n != null && nr(n) === nr(e.currentLine);
|
|
4231
4297
|
}
|
|
4232
|
-
var
|
|
4233
|
-
function
|
|
4298
|
+
var ar = 16, or = 4, sr = 21;
|
|
4299
|
+
function cr(e, t) {
|
|
4234
4300
|
let n = W.views[e];
|
|
4235
4301
|
if (n?.type !== "grid" || !n.rowField) return [];
|
|
4236
|
-
let r = [], i = Math.min(
|
|
4237
|
-
for (let e =
|
|
4302
|
+
let r = [], i = Math.min(sr, t.lines.length - 1);
|
|
4303
|
+
for (let e = or; e <= i; e += 1) {
|
|
4238
4304
|
let i = Q(t.lines[e] ?? ""), a = n.rowField;
|
|
4239
|
-
if (i.length <= a.x + a.width || !
|
|
4240
|
-
let o =
|
|
4305
|
+
if (i.length <= a.x + a.width || !lr(i[a.x + a.width])) continue;
|
|
4306
|
+
let o = tr(n, i);
|
|
4241
4307
|
o.rowIndex != null && r.push({
|
|
4242
4308
|
...o,
|
|
4243
4309
|
screenRow: e
|
|
@@ -4245,11 +4311,11 @@ function nr(e, t) {
|
|
|
4245
4311
|
}
|
|
4246
4312
|
return r;
|
|
4247
4313
|
}
|
|
4248
|
-
var
|
|
4249
|
-
function
|
|
4314
|
+
var lr = (e) => e === " " || /^[^a-zA-Z0-9-]$/.test(e);
|
|
4315
|
+
function ur(e, t) {
|
|
4250
4316
|
let n = W.views[e];
|
|
4251
4317
|
if (n?.type !== "grid") return null;
|
|
4252
|
-
let r =
|
|
4318
|
+
let r = cr(e, t), i = (e) => !!e && e !== " " && lr(e);
|
|
4253
4319
|
if (e === "song") return {
|
|
4254
4320
|
tracks: (n.columns ?? []).filter((e) => e.type === "chainRef").map((e) => r.find((n) => i(Q(t.lines[n.screenRow] ?? "")[e.x - 1]))?.rowIndex ?? null),
|
|
4255
4321
|
row: null
|
|
@@ -4263,25 +4329,25 @@ function ir(e, t) {
|
|
|
4263
4329
|
row: null
|
|
4264
4330
|
};
|
|
4265
4331
|
}
|
|
4266
|
-
function
|
|
4332
|
+
function dr(e, t, n, r) {
|
|
4267
4333
|
let i = (t.cursorPos?.y ?? -1) - r;
|
|
4268
4334
|
if (i < 0) return null;
|
|
4269
4335
|
let a = [], o = null;
|
|
4270
|
-
for (let t = 0; t <
|
|
4336
|
+
for (let t = 0; t < ar; t += 1) {
|
|
4271
4337
|
let r = n.lines[i + t];
|
|
4272
4338
|
if (r == null) return null;
|
|
4273
|
-
let s = Q(r), c =
|
|
4339
|
+
let s = Q(r), c = tr(e, s);
|
|
4274
4340
|
if (c.rowIndex !== t) return null;
|
|
4275
4341
|
a.push(c);
|
|
4276
4342
|
let l = s.indexOf("^^");
|
|
4277
|
-
o == null && l >= 0 && (o =
|
|
4343
|
+
o == null && l >= 0 && (o = fr(e, l));
|
|
4278
4344
|
}
|
|
4279
4345
|
return {
|
|
4280
4346
|
steps: a,
|
|
4281
4347
|
carriedRepLane: o
|
|
4282
4348
|
};
|
|
4283
4349
|
}
|
|
4284
|
-
function
|
|
4350
|
+
function fr(e, t) {
|
|
4285
4351
|
let n = [];
|
|
4286
4352
|
for (let r = 1; r <= 3; r += 1) {
|
|
4287
4353
|
let i = e.columns?.find((e) => e.key === `fx${r}cmd`), a = e.columns?.find((e) => e.key === `fx${r}val`);
|
|
@@ -4295,8 +4361,8 @@ function or(e, t) {
|
|
|
4295
4361
|
let r = Math.min(...n.map((e) => e.dist)), i = n.filter((e) => e.dist === r);
|
|
4296
4362
|
return r <= 1 && i.length === 1 ? i[0].lane : null;
|
|
4297
4363
|
}
|
|
4298
|
-
function
|
|
4299
|
-
let t =
|
|
4364
|
+
function pr(e) {
|
|
4365
|
+
let t = Rn(e.fields.interval?.rawValue ?? "");
|
|
4300
4366
|
if (!t) return null;
|
|
4301
4367
|
let n = e.fields.en?.rawValue.toUpperCase(), r = parseFloat(e.fields.offset?.rawValue ?? "");
|
|
4302
4368
|
return {
|
|
@@ -4306,15 +4372,15 @@ function sr(e) {
|
|
|
4306
4372
|
offset: Number.isNaN(r) ? null : r
|
|
4307
4373
|
};
|
|
4308
4374
|
}
|
|
4309
|
-
function
|
|
4375
|
+
function mr(e, t) {
|
|
4310
4376
|
let n = /* @__PURE__ */ new Map();
|
|
4311
4377
|
for (let r of t.lines) {
|
|
4312
|
-
let t =
|
|
4378
|
+
let t = tr(e, Q(r)), i = pr(t), a = t.fields.en?.rawValue.toUpperCase();
|
|
4313
4379
|
!i || a !== "ON" && a !== "OFF" && a !== "--" || n.has(i.interval) || n.set(i.interval, i);
|
|
4314
4380
|
}
|
|
4315
4381
|
return n.size === Z.length ? Z.map((e) => n.get(e)) : null;
|
|
4316
4382
|
}
|
|
4317
|
-
function
|
|
4383
|
+
function hr(e, t, n, r) {
|
|
4318
4384
|
let i = {
|
|
4319
4385
|
...r,
|
|
4320
4386
|
isGridView: !1,
|
|
@@ -4331,7 +4397,7 @@ function lr(e, t, n, r) {
|
|
|
4331
4397
|
resetsRelative: null,
|
|
4332
4398
|
scaleNote: null,
|
|
4333
4399
|
scale: null
|
|
4334
|
-
}, a = e.cursorPos, o = a ? a.x - 1 : 0, s = a &&
|
|
4400
|
+
}, a = e.cursorPos, o = a ? a.x - 1 : 0, s = a && ir(e, t) ? t : null, c = s && a ? Q(s.lines[a.y] ?? "") : e.currentLine ?? "";
|
|
4335
4401
|
if (!c.trim()) return i;
|
|
4336
4402
|
let l = s && a ? s.lines.slice(0, a.y + 1).reverse().map(Q) : [c], u = r.viewName === "inst" ? Gt(s ? s.lines.map(Q) : [c]) : null, d = {
|
|
4337
4403
|
instrumentKey: u?.key ?? null,
|
|
@@ -4339,7 +4405,7 @@ function lr(e, t, n, r) {
|
|
|
4339
4405
|
};
|
|
4340
4406
|
if (!s && a && n.kind == null) for (let e = 0; e <= Math.min(o, 24); e += 1) {
|
|
4341
4407
|
let t = " ".repeat(e) + c;
|
|
4342
|
-
if (
|
|
4408
|
+
if (nn(n, t, {
|
|
4343
4409
|
...d,
|
|
4344
4410
|
section: Ht(n, [t])
|
|
4345
4411
|
}).cells.some((e) => o >= e.x && o < e.x + e.width)) {
|
|
@@ -4347,17 +4413,17 @@ function lr(e, t, n, r) {
|
|
|
4347
4413
|
break;
|
|
4348
4414
|
}
|
|
4349
4415
|
}
|
|
4350
|
-
let f = Ht(n, s ? l : [c]), { rowId: p, cells: m } =
|
|
4416
|
+
let f = Ht(n, s ? l : [c]), { rowId: p, cells: m } = nn(n, c, {
|
|
4351
4417
|
...d,
|
|
4352
4418
|
section: f
|
|
4353
4419
|
}), h = {};
|
|
4354
|
-
for (let e of m) h[e.key] =
|
|
4420
|
+
for (let e of m) h[e.key] = Zn(e, c);
|
|
4355
4421
|
let g = {
|
|
4356
4422
|
rowIndex: null,
|
|
4357
4423
|
rowKey: "param",
|
|
4358
4424
|
rowId: p,
|
|
4359
4425
|
fields: h
|
|
4360
|
-
}, _ = null, v = a ?
|
|
4426
|
+
}, _ = null, v = a ? er(m, o) : null;
|
|
4361
4427
|
v && (_ = {
|
|
4362
4428
|
...h[v.key],
|
|
4363
4429
|
viewName: r.viewName,
|
|
@@ -4373,10 +4439,10 @@ function lr(e, t, n, r) {
|
|
|
4373
4439
|
lineText: c.trim()
|
|
4374
4440
|
};
|
|
4375
4441
|
}
|
|
4376
|
-
function
|
|
4442
|
+
function gr(e, t) {
|
|
4377
4443
|
let n = e.viewName;
|
|
4378
4444
|
if (!n) return null;
|
|
4379
|
-
let r = W.views[n] ?? null, i = r?.type === "grid", a = r?.title ?? null, o = r?.description ?? null, { viewId: s, isUnsaved: c } =
|
|
4445
|
+
let r = W.views[n] ?? null, i = r?.type === "grid", a = r?.title ?? null, o = r?.description ?? null, { viewId: s, isUnsaved: c } = Yn(e.viewTitle), l = {
|
|
4380
4446
|
viewName: n,
|
|
4381
4447
|
viewTitle: a,
|
|
4382
4448
|
viewDescription: o,
|
|
@@ -4396,7 +4462,7 @@ function ur(e, t) {
|
|
|
4396
4462
|
scaleNote: null,
|
|
4397
4463
|
scale: null
|
|
4398
4464
|
}, d = r?.type === "parameter" ? Bt(n) : null;
|
|
4399
|
-
if (d) return
|
|
4465
|
+
if (d) return hr(e, t, d, l);
|
|
4400
4466
|
if (!i || !r) return {
|
|
4401
4467
|
...u,
|
|
4402
4468
|
isGridView: !1,
|
|
@@ -4410,11 +4476,11 @@ function ur(e, t) {
|
|
|
4410
4476
|
row: null,
|
|
4411
4477
|
activeField: null
|
|
4412
4478
|
};
|
|
4413
|
-
let { line: p } =
|
|
4414
|
-
if (g) return
|
|
4479
|
+
let { line: p } = Xn(f), m = e.cursorPos ? e.cursorPos.x - 1 : 0, h = tr(r, p), g = n === "scale" && !Rn(h.fields.interval?.rawValue ?? "") ? Bt(n) : null;
|
|
4480
|
+
if (g) return hr(e, t, g, l);
|
|
4415
4481
|
let _ = null;
|
|
4416
4482
|
if (e.cursorPos) {
|
|
4417
|
-
let e =
|
|
4483
|
+
let e = er(r.columns ?? [], m);
|
|
4418
4484
|
if (e) {
|
|
4419
4485
|
let t = h.fields[e.key];
|
|
4420
4486
|
t && (_ = {
|
|
@@ -4425,20 +4491,20 @@ function ur(e, t) {
|
|
|
4425
4491
|
}
|
|
4426
4492
|
}
|
|
4427
4493
|
let v = null, y = null, b = null, x = null, S = null, C = null;
|
|
4428
|
-
if (
|
|
4494
|
+
if (ir(e, t)) {
|
|
4429
4495
|
if (n === "phrase" && h.rowIndex != null) {
|
|
4430
|
-
let n =
|
|
4496
|
+
let n = dr(r, e, t, h.rowIndex);
|
|
4431
4497
|
if (n) {
|
|
4432
4498
|
v = n.steps, y = n.carriedRepLane;
|
|
4433
4499
|
let e = _ ? /^fx(\d)(cmd|val)$/.exec(_.key)?.[1] : void 0;
|
|
4434
|
-
e && (b =
|
|
4500
|
+
e && (b = Dn(v, Number(e), h.rowIndex, y === Number(e))), x = An(v, h.rowIndex, y), h.rowIndex > 0 && kn(h) && (S = An(v, h.rowIndex - 1, y));
|
|
4435
4501
|
}
|
|
4436
4502
|
} else if (n === "scale") {
|
|
4437
|
-
let e =
|
|
4438
|
-
e && (C =
|
|
4503
|
+
let e = mr(r, t);
|
|
4504
|
+
e && (C = Vn(e));
|
|
4439
4505
|
}
|
|
4440
4506
|
}
|
|
4441
|
-
let w = n === "scale" ?
|
|
4507
|
+
let w = n === "scale" ? pr(h) : null;
|
|
4442
4508
|
return {
|
|
4443
4509
|
...u,
|
|
4444
4510
|
isGridView: !0,
|
|
@@ -4454,25 +4520,25 @@ function ur(e, t) {
|
|
|
4454
4520
|
scale: C
|
|
4455
4521
|
};
|
|
4456
4522
|
}
|
|
4457
|
-
function
|
|
4458
|
-
if (e.isParameterView) return
|
|
4523
|
+
function _r(e) {
|
|
4524
|
+
if (e.isParameterView) return Er(e);
|
|
4459
4525
|
if (e.viewName === "scale") {
|
|
4460
|
-
let t =
|
|
4526
|
+
let t = Dr(e);
|
|
4461
4527
|
if (t) return t;
|
|
4462
4528
|
}
|
|
4463
4529
|
if (!e.activeField) return $(["location", e.viewTitle ?? e.viewName]);
|
|
4464
|
-
let { activeField: t, row: n } = e, r = $(["field", `${t.label}: ${
|
|
4530
|
+
let { activeField: t, row: n } = e, r = $(["field", `${t.label}: ${kr(t)}`]), i = (t.type === "fxCommand" || t.type === "fxValue") && n ? yr(e, t, n) : [...Sr(e, t), ...Cr(e, t)], a = i.length > 0;
|
|
4465
4531
|
if (t.type === "fxCommand" && !t.isEmpty) {
|
|
4466
|
-
let e = a && /^(REP|RTO)$/i.test(t.rawValue) ? void 0 :
|
|
4532
|
+
let e = a && /^(REP|RTO)$/i.test(t.rawValue) ? void 0 : dn(t.rawValue);
|
|
4467
4533
|
e && r.push({
|
|
4468
4534
|
kind: "fxInfo",
|
|
4469
|
-
text: `(${
|
|
4535
|
+
text: `(${br(e)})`
|
|
4470
4536
|
});
|
|
4471
4537
|
}
|
|
4472
4538
|
if (t.type === "fxValue" && n) {
|
|
4473
4539
|
let e = t.key.replace("val", "cmd"), i = n.fields[e];
|
|
4474
4540
|
if (i && !i.isEmpty) {
|
|
4475
|
-
let e = a && /^(REP|RTO)$/i.test(i.rawValue) ? void 0 :
|
|
4541
|
+
let e = a && /^(REP|RTO)$/i.test(i.rawValue) ? void 0 : dn(i.rawValue), t = e ? `${i.rawValue} (${br(e)})` : i.rawValue;
|
|
4476
4542
|
r.push({
|
|
4477
4543
|
kind: "fxTarget",
|
|
4478
4544
|
text: `for ${t}`
|
|
@@ -4491,8 +4557,8 @@ function dr(e) {
|
|
|
4491
4557
|
}
|
|
4492
4558
|
return r;
|
|
4493
4559
|
}
|
|
4494
|
-
function
|
|
4495
|
-
return
|
|
4560
|
+
function vr(e) {
|
|
4561
|
+
return _r(e).map((e) => e.text).join(" — ");
|
|
4496
4562
|
}
|
|
4497
4563
|
function $(...e) {
|
|
4498
4564
|
return e.flatMap(([e, t]) => t ? [{
|
|
@@ -4500,33 +4566,33 @@ function $(...e) {
|
|
|
4500
4566
|
text: t
|
|
4501
4567
|
}] : []);
|
|
4502
4568
|
}
|
|
4503
|
-
function
|
|
4569
|
+
function yr(e, t, n) {
|
|
4504
4570
|
let r = /^fx(\d)/.exec(t.key)?.[1];
|
|
4505
4571
|
if (!r) return [];
|
|
4506
4572
|
let i = n.fields[`fx${r}cmd`], a = n.fields[`fx${r}val`];
|
|
4507
4573
|
if (!i || i.isEmpty) {
|
|
4508
4574
|
if (e.fxLane?.event !== "continue") return [];
|
|
4509
|
-
let t = e.fxLane.source?.cmd, n = t && q(t) ?
|
|
4510
|
-
return $(["fxLane",
|
|
4575
|
+
let t = e.fxLane.source?.cmd, n = t && q(t) ? Pn(e.relativeFx?.[t]) : null;
|
|
4576
|
+
return $(["fxLane", On(e.fxLane)], ["relative", n]);
|
|
4511
4577
|
}
|
|
4512
|
-
let o = i.rawValue.toUpperCase(), s = e.fxLane && e.fxLane.event !== "none" && e.fxLane.event !== "set" ?
|
|
4578
|
+
let o = i.rawValue.toUpperCase(), s = e.fxLane && e.fxLane.event !== "none" && e.fxLane.event !== "set" ? On(e.fxLane) : null;
|
|
4513
4579
|
if ((o === "REP" || o === "RTO") && e.viewName !== "table") {
|
|
4514
|
-
let t = e.fxLane?.source?.cmd, n = o === "REP" && e.fxLane?.active && t && q(t) ?
|
|
4580
|
+
let t = e.fxLane?.source?.cmd, n = o === "REP" && e.fxLane?.active && t && q(t) ? Pn(e.relativeFx?.[t]) : null;
|
|
4515
4581
|
return $(["fxLane", s], ["relative", n]);
|
|
4516
4582
|
}
|
|
4517
4583
|
if (!a || a.isEmpty || a.hexValue == null) return $(["fxLane", s]);
|
|
4518
|
-
let c = t.type === "fxCommand" ? `value ${
|
|
4584
|
+
let c = t.type === "fxCommand" ? `value ${gn(o, a.hexValue)}: ` : "", l = Tn(o, a.hexValue, {
|
|
4519
4585
|
note: n.fields.note?.isEmpty ? null : n.fields.note?.rawValue,
|
|
4520
4586
|
inTable: e.viewName === "table",
|
|
4521
4587
|
row: n.rowIndex
|
|
4522
4588
|
}), u = null;
|
|
4523
|
-
return q(o) ? u =
|
|
4589
|
+
return q(o) ? u = Pn(e.relativeFx?.[o]) : o === "RET" && e.resetsRelative && (u = Fn(e.resetsRelative)), $(["meaning", l ? `${c}${l}` : null], ["fxLane", s], ["relative", u]);
|
|
4524
4590
|
}
|
|
4525
|
-
function
|
|
4591
|
+
function br(e) {
|
|
4526
4592
|
let t = e.description.replace(/\.$/, "");
|
|
4527
|
-
return e.instrumentTypes ? `${t}; offered by ${e.instrumentTypes.map((e) =>
|
|
4593
|
+
return e.instrumentTypes ? `${t}; offered by ${e.instrumentTypes.map((e) => xr[e] ?? e).join(", ")} instruments` : t;
|
|
4528
4594
|
}
|
|
4529
|
-
var
|
|
4595
|
+
var xr = {
|
|
4530
4596
|
sampler: "Sampler",
|
|
4531
4597
|
macrosynth: "Macrosynth",
|
|
4532
4598
|
fmsynth: "FM Synth",
|
|
@@ -4535,17 +4601,17 @@ var hr = {
|
|
|
4535
4601
|
external: "External",
|
|
4536
4602
|
midiout: "MIDI Out"
|
|
4537
4603
|
};
|
|
4538
|
-
function
|
|
4539
|
-
return t.type !== "instrumentRef" || t.isEmpty || !e.resetsRelative ? [] : $(["relative",
|
|
4604
|
+
function Sr(e, t) {
|
|
4605
|
+
return t.type !== "instrumentRef" || t.isEmpty || !e.resetsRelative ? [] : $(["relative", Fn(e.resetsRelative)]);
|
|
4540
4606
|
}
|
|
4541
|
-
function
|
|
4607
|
+
function Cr(e, t) {
|
|
4542
4608
|
return e.viewName !== "table" || t.key !== "volume" || t.isEmpty || t.hexValue == null || t.hexValue > 127 ? [] : $(["meaning", `plays at ${Math.round(t.hexValue / 127 * 100)}% of the step's velocity`]);
|
|
4543
4609
|
}
|
|
4544
|
-
var
|
|
4610
|
+
var wr = {
|
|
4545
4611
|
MODFX: "ModFX",
|
|
4546
4612
|
DELAY: "Delay",
|
|
4547
4613
|
REVERB: "Reverb"
|
|
4548
|
-
},
|
|
4614
|
+
}, Tr = {
|
|
4549
4615
|
parent: "goes up to the parent directory",
|
|
4550
4616
|
directory: "directory: [EDIT] opens it",
|
|
4551
4617
|
instrumentPreset: "instrument preset: [EDIT] selects it",
|
|
@@ -4553,38 +4619,38 @@ var vr = {
|
|
|
4553
4619
|
m8file: "M8 file: [EDIT] selects it",
|
|
4554
4620
|
file: "file: [EDIT] selects it"
|
|
4555
4621
|
};
|
|
4556
|
-
function
|
|
4622
|
+
function Er(e) {
|
|
4557
4623
|
let t = `${e.viewTitle ?? e.viewName}${e.viewId ? ` ${e.viewId}` : ""}`, n = e.activeField;
|
|
4558
4624
|
if (!n) return $(["location", t], ["line", e.lineText]);
|
|
4559
4625
|
let r = e.instrumentType?.key ? Kt(e.instrumentType.key) : null;
|
|
4560
|
-
return $(["field", `${n.label}: ${
|
|
4626
|
+
return $(["field", `${n.label}: ${kr(n)}`], ["optionInfo", n.valueDescription], ["fieldInfo", n.description], ["fileInfo", n.fileKind && Tr[n.fileKind]], ["instrument", e.instrumentType && `${r?.name ?? e.instrumentType.text} instrument`], ["section", e.section && (wr[e.section] ?? e.section)], ["location", t]);
|
|
4561
4627
|
}
|
|
4562
|
-
function
|
|
4628
|
+
function Dr(e) {
|
|
4563
4629
|
let t = `${e.viewTitle ?? e.viewName}${e.viewId ? ` ${e.viewId}` : ""}`, n = e.activeField, r = e.scaleNote;
|
|
4564
4630
|
if (!n || !r) return e.lineText ? $(["location", t], ["line", e.lineText]) : null;
|
|
4565
4631
|
let { interval: i, enabled: a, offset: o } = r, s;
|
|
4566
4632
|
if (n.key === "offset") {
|
|
4567
|
-
let e = o == null ? `detune of ${i}` : o === 0 ? `${i} is not detuned` : `${i} is detuned by ${
|
|
4633
|
+
let e = o == null ? `detune of ${i}` : o === 0 ? `${i} is not detuned` : `${i} is detuned by ${Un(o)}`;
|
|
4568
4634
|
s = $(["field", `${n.label}: ${n.rawValue || "(empty)"}`], ["meaning", e], ["meaning", a === !1 ? "(note is OFF)" : null]);
|
|
4569
4635
|
} else {
|
|
4570
4636
|
let e = a === !0 ? "is in" : a === !1 ? "is not in" : "is not yet set in";
|
|
4571
|
-
s = $(["field", `${n.label}: ${n.key === "en" ? n.rawValue.toUpperCase() || "(unset)" : i}`], ["meaning", i], ["meaning",
|
|
4637
|
+
s = $(["field", `${n.label}: ${n.key === "en" ? n.rawValue.toUpperCase() || "(unset)" : i}`], ["meaning", i], ["meaning", zn(i)], ["meaning", `${e} the scale`]);
|
|
4572
4638
|
}
|
|
4573
4639
|
if (e.scale) {
|
|
4574
|
-
let [t, n] =
|
|
4640
|
+
let [t, n] = Hn(e.scale);
|
|
4575
4641
|
s.push(...$(["scale", `Scale: ${t}`], ["scale", n]));
|
|
4576
4642
|
}
|
|
4577
4643
|
return [...s, ...$(["location", `${t} row ${i}`])];
|
|
4578
4644
|
}
|
|
4579
|
-
function
|
|
4645
|
+
function Or(e) {
|
|
4580
4646
|
let t = e.unit ?? "";
|
|
4581
4647
|
if (e.values && e.parts) {
|
|
4582
4648
|
let n = e.hexValue != null, r = e.values.map((e) => n ? e.toString(16).toUpperCase().padStart(2, "0") : String(e)), i = e.parts.map((e, n) => `${e} ${r[n] ?? "?"}${t}`).join(", ");
|
|
4583
|
-
return `${r.join(":")} (${i})`;
|
|
4649
|
+
return `${r.join(e.rawValue.includes("/") ? "/" : ":")} (${i})`;
|
|
4584
4650
|
}
|
|
4585
4651
|
return e.hexValue == null ? e.numericValue == null ? e.text ?? e.rawValue : `${e.rawValue}${t}` : `${e.rawValue.slice(0, 2)}h (dec ${e.hexValue})${e.text ? ` ${e.text}` : ""}`;
|
|
4586
4652
|
}
|
|
4587
|
-
function
|
|
4653
|
+
function kr(e) {
|
|
4588
4654
|
if (e.isEmpty) return "(empty)";
|
|
4589
4655
|
let t = e.type === "name" || e.type === "fileEntry" ? e : {
|
|
4590
4656
|
...e,
|
|
@@ -4611,26 +4677,26 @@ function Cr(e) {
|
|
|
4611
4677
|
case "fileEntry": return t.text ?? t.rawValue;
|
|
4612
4678
|
case "name": return `"${t.rawValue}"`;
|
|
4613
4679
|
case "option": return t.hexValue != null && t.text ? `${t.rawValue.slice(0, 2)} ${t.text}` : t.text ?? t.rawValue;
|
|
4614
|
-
case "parameter": return
|
|
4615
|
-
case "noteInterval": return `Interval ${
|
|
4680
|
+
case "parameter": return Or(t);
|
|
4681
|
+
case "noteInterval": return `Interval ${Rn(t.rawValue) ?? t.rawValue}`;
|
|
4616
4682
|
case "semitoneOffset": return t.isEmpty ? "(empty)" : `${t.rawValue} st`;
|
|
4617
4683
|
default: return t.rawValue;
|
|
4618
4684
|
}
|
|
4619
4685
|
}
|
|
4620
4686
|
//#endregion
|
|
4621
4687
|
//#region src/client.ts
|
|
4622
|
-
var
|
|
4688
|
+
var Ar = "yam8d-external-app", jr = 3e3, Mr = (e) => {
|
|
4623
4689
|
let t = e.remoteHandle();
|
|
4624
4690
|
return {
|
|
4625
4691
|
call: (e, ...n) => t.call(e, ...n),
|
|
4626
4692
|
on: (e, n) => (t.addEventListener(e, n), () => t.removeEventListener(e, n)),
|
|
4627
4693
|
close: () => e.close()
|
|
4628
4694
|
};
|
|
4629
|
-
},
|
|
4695
|
+
}, Nr = (e) => ({
|
|
4630
4696
|
call: (t, ...n) => e.methods[t](...n),
|
|
4631
4697
|
on: (t, n) => e.on(t, n),
|
|
4632
4698
|
close: () => e.dispose()
|
|
4633
|
-
}),
|
|
4699
|
+
}), Pr = (e) => {
|
|
4634
4700
|
let t = [];
|
|
4635
4701
|
return {
|
|
4636
4702
|
messenger: {
|
|
@@ -4644,21 +4710,21 @@ var wr = "yam8d-external-app", Tr = 3e3, Er = (e) => {
|
|
|
4644
4710
|
for (let e of t.splice(0)) e();
|
|
4645
4711
|
}
|
|
4646
4712
|
};
|
|
4647
|
-
},
|
|
4713
|
+
}, Fr = () => {
|
|
4648
4714
|
if (typeof window > "u") return !1;
|
|
4649
4715
|
try {
|
|
4650
4716
|
return window.parent !== window;
|
|
4651
4717
|
} catch {
|
|
4652
4718
|
return !0;
|
|
4653
4719
|
}
|
|
4654
|
-
},
|
|
4720
|
+
}, Ir = (e) => e instanceof DOMException && (e.name === "NotFoundError" || e.name === "AbortError"), Lr = () => {
|
|
4655
4721
|
let e = typeof navigator > "u" ? null : navigator;
|
|
4656
4722
|
return {
|
|
4657
4723
|
serial: !!e && "serial" in e,
|
|
4658
4724
|
usb: !!e && "usb" in e,
|
|
4659
4725
|
midi: !!e && "requestMIDIAccess" in e
|
|
4660
4726
|
};
|
|
4661
|
-
},
|
|
4727
|
+
}, Rr = () => ({
|
|
4662
4728
|
viewName: null,
|
|
4663
4729
|
viewTitle: null,
|
|
4664
4730
|
minimapKey: null,
|
|
@@ -4675,9 +4741,9 @@ var wr = "yam8d-external-app", Tr = 3e3, Er = (e) => {
|
|
|
4675
4741
|
fontMode: null,
|
|
4676
4742
|
systemInfo: null,
|
|
4677
4743
|
macroRunning: !1
|
|
4678
|
-
}),
|
|
4744
|
+
}), zr = class {
|
|
4679
4745
|
constructor(e = {}) {
|
|
4680
|
-
this.backend = null, this.backendUnsubscribers = [], this.device = null, this._mode = null, this.audio = null, this.connecting = null, this.stateCallbacks = /* @__PURE__ */ new Set(), this.viewCallbacks = /* @__PURE__ */ new Set(), this.cursorCallbacks = /* @__PURE__ */ new Set(), this.textCallbacks = /* @__PURE__ */ new Set(), this.keyCallbacks = /* @__PURE__ */ new Set(), this.transportCallbacks = /* @__PURE__ */ new Set(), this.connectionCallbacks = /* @__PURE__ */ new Set(), this._state =
|
|
4746
|
+
this.backend = null, this.backendUnsubscribers = [], this.device = null, this._mode = null, this.audio = null, this.connecting = null, this.stateCallbacks = /* @__PURE__ */ new Set(), this.viewCallbacks = /* @__PURE__ */ new Set(), this.cursorCallbacks = /* @__PURE__ */ new Set(), this.textCallbacks = /* @__PURE__ */ new Set(), this.keyCallbacks = /* @__PURE__ */ new Set(), this.transportCallbacks = /* @__PURE__ */ new Set(), this.connectionCallbacks = /* @__PURE__ */ new Set(), this._state = Rr(), this._screen = null, this.screenRefreshing = !1, this.screenDirty = !1, this.config = e;
|
|
4681
4747
|
}
|
|
4682
4748
|
get state() {
|
|
4683
4749
|
return this._state;
|
|
@@ -4699,11 +4765,11 @@ var wr = "yam8d-external-app", Tr = 3e3, Er = (e) => {
|
|
|
4699
4765
|
}
|
|
4700
4766
|
async resolveMode() {
|
|
4701
4767
|
let e = this.config.mode ?? "auto";
|
|
4702
|
-
if (e === "standalone" || e === "auto" && !
|
|
4768
|
+
if (e === "standalone" || e === "auto" && !Fr()) {
|
|
4703
4769
|
await this.startStandalone();
|
|
4704
4770
|
return;
|
|
4705
4771
|
}
|
|
4706
|
-
let t = typeof window < "u" && window.name === "yam8d-external-app", n = e === "host" || t ? null : this.config.handshakeTimeoutMs ??
|
|
4772
|
+
let t = typeof window < "u" && window.name === "yam8d-external-app", n = e === "host" || t ? null : this.config.handshakeTimeoutMs ?? jr;
|
|
4707
4773
|
await this.handshake(n) || (this.config.debug && console.log("[M8 SDK] No yam8d host answered, switching to standalone mode"), await this.startStandalone());
|
|
4708
4774
|
}
|
|
4709
4775
|
async handshake(r) {
|
|
@@ -4715,10 +4781,10 @@ var wr = "yam8d-external-app", Tr = 3e3, Er = (e) => {
|
|
|
4715
4781
|
this.config.debug && (i = t(i, (e, ...t) => {
|
|
4716
4782
|
console.log("[M8 SDK]", e, ...t);
|
|
4717
4783
|
}));
|
|
4718
|
-
let a =
|
|
4784
|
+
let a = Pr(i), o = e(a.messenger, { ping: async () => "pong" }), s, c = new Promise((e) => {
|
|
4719
4785
|
r !== null && (s = setTimeout(() => e(null), r));
|
|
4720
4786
|
}), l = await Promise.race([o, c]);
|
|
4721
|
-
return clearTimeout(s), l ? (this._mode = "host", await this.attach(
|
|
4787
|
+
return clearTimeout(s), l ? (this._mode = "host", await this.attach(Mr(l)), l.localHandle().emit("ready", void 0), !0) : (a.dispose(), !1);
|
|
4722
4788
|
}
|
|
4723
4789
|
async startStandalone() {
|
|
4724
4790
|
if (this._mode = "standalone", this.config.autoConnect !== !1) try {
|
|
@@ -4744,14 +4810,14 @@ var wr = "yam8d-external-app", Tr = 3e3, Er = (e) => {
|
|
|
4744
4810
|
});
|
|
4745
4811
|
break;
|
|
4746
4812
|
} catch (r) {
|
|
4747
|
-
if (a = r, t && !
|
|
4813
|
+
if (a = r, t && !Ir(r) && (i = await ee(() => n.connect({
|
|
4748
4814
|
transport: e,
|
|
4749
4815
|
prompt: !1
|
|
4750
4816
|
}), { maxAttempts: 2 }), i)) break;
|
|
4751
4817
|
}
|
|
4752
4818
|
if (!i) throw a;
|
|
4753
4819
|
let o = Pt(i, { debug: this.config.debug });
|
|
4754
|
-
this.device = i, await this.attach(
|
|
4820
|
+
this.device = i, await this.attach(Nr(o)), i.commands.resetScreen();
|
|
4755
4821
|
let s = i;
|
|
4756
4822
|
i.closed.then(() => {
|
|
4757
4823
|
this.device === s && (this.config.debug && console.log("[M8 SDK] Device connection ended"), this.device = null, this.detach());
|
|
@@ -4901,7 +4967,7 @@ var wr = "yam8d-external-app", Tr = 3e3, Er = (e) => {
|
|
|
4901
4967
|
}, e;
|
|
4902
4968
|
}
|
|
4903
4969
|
async captureSnapshot() {
|
|
4904
|
-
let [e, t] = await Promise.all([this.fetchState(), this.getScreen()]), n =
|
|
4970
|
+
let [e, t] = await Promise.all([this.fetchState(), this.getScreen()]), n = gr(e, t);
|
|
4905
4971
|
return {
|
|
4906
4972
|
capturedAt: Date.now(),
|
|
4907
4973
|
state: {
|
|
@@ -4914,8 +4980,8 @@ var wr = "yam8d-external-app", Tr = 3e3, Er = (e) => {
|
|
|
4914
4980
|
deviceModel: e.deviceModel
|
|
4915
4981
|
},
|
|
4916
4982
|
semantic: n,
|
|
4917
|
-
description: n ?
|
|
4918
|
-
descriptionParts: n ?
|
|
4983
|
+
description: n ? vr(n) : null,
|
|
4984
|
+
descriptionParts: n ? _r(n) : null,
|
|
4919
4985
|
screen: t
|
|
4920
4986
|
};
|
|
4921
4987
|
}
|
|
@@ -4944,23 +5010,23 @@ var wr = "yam8d-external-app", Tr = 3e3, Er = (e) => {
|
|
|
4944
5010
|
this.audio?.disconnect(), this.closeDevice(), this.detach(), this.stateCallbacks.clear(), this.viewCallbacks.clear(), this.cursorCallbacks.clear(), this.textCallbacks.clear(), this.keyCallbacks.clear(), this.transportCallbacks.clear(), this.connectionCallbacks.clear();
|
|
4945
5011
|
}
|
|
4946
5012
|
getSemanticContext() {
|
|
4947
|
-
return
|
|
5013
|
+
return gr(this._state, this._screen);
|
|
4948
5014
|
}
|
|
4949
5015
|
describeContext() {
|
|
4950
|
-
let e =
|
|
4951
|
-
return e ?
|
|
5016
|
+
let e = gr(this._state, this._screen);
|
|
5017
|
+
return e ? vr(e) : null;
|
|
4952
5018
|
}
|
|
4953
5019
|
describeContextParts() {
|
|
4954
|
-
let e =
|
|
4955
|
-
return e ?
|
|
5020
|
+
let e = gr(this._state, this._screen);
|
|
5021
|
+
return e ? _r(e) : null;
|
|
4956
5022
|
}
|
|
4957
5023
|
};
|
|
4958
|
-
async function
|
|
4959
|
-
let t = new
|
|
5024
|
+
async function Br(e = {}) {
|
|
5025
|
+
let t = new zr(e);
|
|
4960
5026
|
return await t.connect(), t;
|
|
4961
5027
|
}
|
|
4962
|
-
function
|
|
4963
|
-
let t = new
|
|
5028
|
+
function Vr(e = {}) {
|
|
5029
|
+
let t = new zr(e);
|
|
4964
5030
|
return {
|
|
4965
5031
|
client: t,
|
|
4966
5032
|
connect: async () => {
|
|
@@ -4968,10 +5034,10 @@ function Fr(e = {}) {
|
|
|
4968
5034
|
}
|
|
4969
5035
|
};
|
|
4970
5036
|
}
|
|
4971
|
-
var
|
|
4972
|
-
createM8Client:
|
|
4973
|
-
createM8ClientSync:
|
|
4974
|
-
},
|
|
5037
|
+
var Hr = {
|
|
5038
|
+
createM8Client: Br,
|
|
5039
|
+
createM8ClientSync: Vr
|
|
5040
|
+
}, Ur = [
|
|
4975
5041
|
{
|
|
4976
5042
|
role: "background",
|
|
4977
5043
|
label: "BACKGROUND"
|
|
@@ -5024,7 +5090,7 @@ var Ir = {
|
|
|
5024
5090
|
role: "meterPeak",
|
|
5025
5091
|
label: "METER PEAK"
|
|
5026
5092
|
}
|
|
5027
|
-
],
|
|
5093
|
+
], Wr = "themesettings", Gr = (e) => e.replace(/\s+/g, "").toUpperCase(), Kr = (e) => Math.max(0, Math.min(255, Math.round(e))).toString(16).padStart(2, "0"), qr = (e, t, n) => `#${Kr(e)}${Kr(t)}${Kr(n)}`, Jr = (e, t, n) => {
|
|
5028
5094
|
let r = e / 256 * 6, i = t / 255, a = n / 255, o = Math.floor(r) % 6, s = r - Math.floor(r), c = a * (1 - i), l = a * (1 - s * i), u = a * (1 - (1 - s) * i), [d, f, p] = [
|
|
5029
5095
|
[
|
|
5030
5096
|
a,
|
|
@@ -5057,14 +5123,14 @@ var Ir = {
|
|
|
5057
5123
|
l
|
|
5058
5124
|
]
|
|
5059
5125
|
][o];
|
|
5060
|
-
return
|
|
5061
|
-
},
|
|
5062
|
-
function
|
|
5126
|
+
return qr(d * 255, f * 255, p * 255);
|
|
5127
|
+
}, Yr = new Map(Ur.map(({ role: e, label: t }) => [Gr(t), e]));
|
|
5128
|
+
function Xr(e) {
|
|
5063
5129
|
let t = "rgb", n = null, r = {};
|
|
5064
5130
|
for (let i of e.lines) {
|
|
5065
5131
|
let e = i.replace(/[{}]/g, "0"), a = /^\s*MODE\s+([A-Z])\s+([A-Z])\s+([A-Z])\b/i.exec(e);
|
|
5066
5132
|
if (a) {
|
|
5067
|
-
t =
|
|
5133
|
+
t = Gr(a.slice(1).join("")) === "HSV" ? "hsv" : "rgb";
|
|
5068
5134
|
continue;
|
|
5069
5135
|
}
|
|
5070
5136
|
let o = /^\s*THEME\s+NAME\s+(\S.*?)\s*$/i.exec(e);
|
|
@@ -5075,23 +5141,23 @@ function Wr(e) {
|
|
|
5075
5141
|
}
|
|
5076
5142
|
let s = /^\s*([A-Z][A-Z:/. ]*?)\s+([0-9A-F]{2})\s+([0-9A-F]{2})\s+([0-9A-F]{2})(?:\s|$)/i.exec(e);
|
|
5077
5143
|
if (!s) continue;
|
|
5078
|
-
let c =
|
|
5144
|
+
let c = Yr.get(Gr(s[1]));
|
|
5079
5145
|
if (!c || r[c]) continue;
|
|
5080
5146
|
let [l, u, d] = s.slice(2, 5).map((e) => parseInt(e, 16));
|
|
5081
|
-
r[c] = t === "hsv" ?
|
|
5147
|
+
r[c] = t === "hsv" ? Jr(l, u, d) : qr(l, u, d);
|
|
5082
5148
|
}
|
|
5083
|
-
return
|
|
5149
|
+
return Ur.some(({ role: e }) => !r[e]) ? null : {
|
|
5084
5150
|
colors: r,
|
|
5085
5151
|
mode: t,
|
|
5086
5152
|
name: n
|
|
5087
5153
|
};
|
|
5088
5154
|
}
|
|
5089
|
-
var
|
|
5090
|
-
function
|
|
5091
|
-
let t = {}, n =
|
|
5155
|
+
var Zr = (e) => e ? qr(e.r, e.g, e.b) : void 0;
|
|
5156
|
+
function Qr(e) {
|
|
5157
|
+
let t = {}, n = Zr(e.backgroundColor), r = Zr(e.titleColor);
|
|
5092
5158
|
return n && (t.background = n), r && (t.textTitles = r), t;
|
|
5093
5159
|
}
|
|
5094
5160
|
//#endregion
|
|
5095
|
-
export { I as M8KeyMask, j as M8_AUDIO_CAPTURE_CONSTRAINTS,
|
|
5161
|
+
export { I as M8KeyMask, j as M8_AUDIO_CAPTURE_CONSTRAINTS, Ur as M8_THEME_ROLES, Wr as M8_THEME_VIEW, pn as RELATIVE_FX_RULE, rr as SCREEN_MARGIN, Ar as YAM8D_FRAME_NAME, F as createM8Audio, Br as createM8Client, Vr as createM8ClientSync, A as createM8Connection, Pt as createM8Engine, Hr as default, vr as describeContext, _r as describeContextParts, kr as formatFieldValue, Lr as getDeviceSupport, fn as getInstrumentFxCommands, P as getM8InputStream, gr as getSemanticContext, dn as lookupFxCommand, Qr as observeThemeColors, cr as parseGridScreen, Xr as parseThemeScreen, Jn as parseViewTitle, te as pressKeys, ur as readPlayPositions };
|
|
5096
5162
|
|
|
5097
5163
|
//# sourceMappingURL=index.js.map
|