@yam8d/m8-sdk 0.3.1 → 0.3.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 CHANGED
@@ -7,386 +7,35 @@ var r = {
7
7
  playbackIndicator: "The M8 renders a '>' character one column to the left of the first data column when that step/row/track is currently playing. This character is part of the text stream; the editing cursor is a separate rect overlay.",
8
8
  emptyCell: "An empty or unused cell displays '--' (2 chars) or '---' (3 chars) or '---00' (command+value). Parsed hexValue will be null for these.",
9
9
  relativeHex: "Transpose and some FX values use relative hex: 00 = no change, 01-7F = +1-127, FF-80 = -1-128. See 'Relative and Absolute FX Commands' in the manual.",
10
- rowIndex: "Row/step indices are parsed from the leftmost characters of currentLine. They are hex for all grid views."
10
+ rowIndex: "Row/step indices are parsed from the leftmost characters of currentLine. They are hex for all grid views.",
11
+ titleAsterisk: "A '*' next to the item ID in the screen title (e.g. 'PHRASE 03*') indicates the item is used elsewhere in the chain or song (phrase view); on other views it marks unsaved changes. See 'An asterisk next to the phrase number' in the manual."
11
12
  },
12
13
  fieldTypes: {
13
14
  chainRef: "Reference to a chain number (hex 00-FF). '--' means empty/unused.",
14
15
  phraseRef: "Reference to a phrase number (hex 00-FF). '--' means empty/unused.",
15
16
  note: "Musical note in M8 format: [A-G][#|-][0-9] e.g. 'C-4', 'A#3'. '---' = empty. 'OFF' = note-off.",
16
- velocity: "Note velocity 00-7F (hex). Default is 64 (hex). '--' = inherit.",
17
+ velocity: "Note velocity 00-7F (hex), from 00 (silence) to 7F (maximum). Default is 64 (hex). '--' = inherit.",
17
18
  instrumentRef: "Instrument number 00-7F (hex). '--' = no retrigger (keep current instrument).",
18
19
  fxCommand: "3-character sequencer or instrument FX command name, e.g. 'KIL', 'ARP', 'DEL'. '---' = none.",
19
20
  fxValue: "2-char hex value 00-FF accompanying an FX command. Interpretation depends on the command.",
20
21
  transpose: "Semitone or tick transpose. Relative: 00=none, 01-7F=+1-+127, FF-80=-1--128.",
21
22
  ticks: "Number of ticks this step consumes in a groove (hex 01-FF). '00' skips the step. '--' = empty (groove loops at this point).",
22
23
  volume: "Volume multiplier 00-FF (hex). Multiplied with the phrase-row velocity. '--' = no override.",
23
- ppq: "Pulses Per Quarter note: resolution of the groove clock (decimal). Only editable on groove row 0.",
24
+ ppq: "Pulses Per Quarter note: resolution of the groove clock (decimal). One of 24 (default), 48, 96 or 192. Only present on groove row 0; absent on all other rows.",
24
25
  instrumentName: "Instrument name string (up to 12 characters). Text field, no hex value.",
25
26
  eqSlot: "EQ slot assignment (hex). '--' = no EQ applied to this instrument.",
26
- rowIndex: "The positional index of this row in the current view (song row, chain position, phrase step, etc.)."
27
- },
28
- views: {
29
- song: {
30
- title: "Song View",
31
- type: "grid",
32
- description: "Arranges chains across 8 independent tracks to form the song structure. Each row is a song position; each column is a track.",
33
- rowField: {
34
- x: 0,
35
- width: 2,
36
- parse: "hex",
37
- type: "rowIndex",
38
- key: "songRow",
39
- description: "Song row 00-FF. Each track loops back to row 00 when it reaches '--'."
40
- },
41
- columns: [
42
- {
43
- x: 3,
44
- width: 2,
45
- key: "track1",
46
- type: "chainRef",
47
- label: "Track 1",
48
- meta: { trackIndex: 1 }
49
- },
50
- {
51
- x: 6,
52
- width: 2,
53
- key: "track2",
54
- type: "chainRef",
55
- label: "Track 2",
56
- meta: { trackIndex: 2 }
57
- },
58
- {
59
- x: 9,
60
- width: 2,
61
- key: "track3",
62
- type: "chainRef",
63
- label: "Track 3",
64
- meta: { trackIndex: 3 }
65
- },
66
- {
67
- x: 12,
68
- width: 2,
69
- key: "track4",
70
- type: "chainRef",
71
- label: "Track 4",
72
- meta: { trackIndex: 4 }
73
- },
74
- {
75
- x: 15,
76
- width: 2,
77
- key: "track5",
78
- type: "chainRef",
79
- label: "Track 5",
80
- meta: { trackIndex: 5 }
81
- },
82
- {
83
- x: 18,
84
- width: 2,
85
- key: "track6",
86
- type: "chainRef",
87
- label: "Track 6",
88
- meta: { trackIndex: 6 }
89
- },
90
- {
91
- x: 21,
92
- width: 2,
93
- key: "track7",
94
- type: "chainRef",
95
- label: "Track 7",
96
- meta: { trackIndex: 7 }
97
- },
98
- {
99
- x: 24,
100
- width: 2,
101
- key: "track8",
102
- type: "chainRef",
103
- label: "Track 8",
104
- meta: { trackIndex: 8 }
105
- }
106
- ]
107
- },
108
- chain: {
109
- title: "Chain View",
110
- type: "grid",
111
- description: "An ordered list of up to 16 phrases. The first '--' phrase ends the chain and loops back to the song.",
112
- rowField: {
113
- x: 0,
114
- width: 1,
115
- parse: "hex",
116
- type: "rowIndex",
117
- key: "chainPos",
118
- description: "Position within the chain (0-F, max 16 entries)."
119
- },
120
- columns: [{
121
- x: 2,
122
- width: 2,
123
- key: "phrase",
124
- type: "phraseRef",
125
- label: "Phrase (PH)",
126
- description: "Phrase number to play at this chain position."
127
- }, {
128
- x: 5,
129
- width: 2,
130
- key: "transpose",
131
- type: "transpose",
132
- label: "Transpose (TSP)",
133
- description: "Optional note transpose in semitones applied to every note in the phrase (relative hex)."
134
- }]
135
- },
136
- phrase: {
137
- title: "Phrase View",
138
- type: "grid",
139
- description: "A 16-step sequence. Each step holds a note, velocity, instrument assignment, and up to 3 FX command+value pairs.",
140
- rowField: {
141
- x: 0,
142
- width: 1,
143
- parse: "hex",
144
- type: "rowIndex",
145
- key: "step",
146
- description: "Step index 0-F (16th note by default; altered by groove)."
147
- },
148
- columns: [
149
- {
150
- x: 2,
151
- width: 3,
152
- key: "note",
153
- type: "note",
154
- label: "Note (N)"
155
- },
156
- {
157
- x: 6,
158
- width: 2,
159
- key: "vel",
160
- type: "velocity",
161
- label: "Velocity (V)"
162
- },
163
- {
164
- x: 9,
165
- width: 2,
166
- key: "inst",
167
- type: "instrumentRef",
168
- label: "Instrument (I)"
169
- },
170
- {
171
- x: 12,
172
- width: 3,
173
- key: "fx1cmd",
174
- type: "fxCommand",
175
- label: "FX1 Command"
176
- },
177
- {
178
- x: 15,
179
- width: 2,
180
- key: "fx1val",
181
- type: "fxValue",
182
- label: "FX1 Value"
183
- },
184
- {
185
- x: 18,
186
- width: 3,
187
- key: "fx2cmd",
188
- type: "fxCommand",
189
- label: "FX2 Command"
190
- },
191
- {
192
- x: 21,
193
- width: 2,
194
- key: "fx2val",
195
- type: "fxValue",
196
- label: "FX2 Value"
197
- },
198
- {
199
- x: 24,
200
- width: 3,
201
- key: "fx3cmd",
202
- type: "fxCommand",
203
- label: "FX3 Command"
204
- },
205
- {
206
- x: 27,
207
- width: 2,
208
- key: "fx3val",
209
- type: "fxValue",
210
- label: "FX3 Value"
211
- }
212
- ]
213
- },
214
- table: {
215
- title: "Table View",
216
- type: "grid",
217
- description: "A 16-step mini-sequencer that runs alongside an instrument. Used for arpeggios, multi-stage envelopes, and automated FX.",
218
- rowField: {
219
- x: 0,
220
- width: 1,
221
- parse: "hex",
222
- type: "rowIndex",
223
- key: "step",
224
- description: "Table step 0-F. Loops from bottom unless a HOP command redirects."
225
- },
226
- columns: [
227
- {
228
- x: 2,
229
- width: 2,
230
- key: "transpose",
231
- type: "transpose",
232
- label: "Transpose (N)",
233
- description: "Transposes the instrument for this step (relative hex). '--' = no transpose."
234
- },
235
- {
236
- x: 5,
237
- width: 2,
238
- key: "volume",
239
- type: "volume",
240
- label: "Volume (V)",
241
- description: "Volume multiplier applied on top of the phrase velocity (hex). '--' = no override."
242
- },
243
- {
244
- x: 8,
245
- width: 3,
246
- key: "fx1cmd",
247
- type: "fxCommand",
248
- label: "FX1 Command",
249
- description: "3-char command name for table FX slot 1."
250
- },
251
- {
252
- x: 11,
253
- width: 2,
254
- key: "fx1val",
255
- type: "fxValue",
256
- label: "FX1 Value",
257
- description: "Value for table FX1."
258
- },
259
- {
260
- x: 14,
261
- width: 3,
262
- key: "fx2cmd",
263
- type: "fxCommand",
264
- label: "FX2 Command",
265
- description: "3-char command name for table FX slot 2."
266
- },
267
- {
268
- x: 17,
269
- width: 2,
270
- key: "fx2val",
271
- type: "fxValue",
272
- label: "FX2 Value",
273
- description: "Value for table FX2."
274
- },
275
- {
276
- x: 20,
277
- width: 3,
278
- key: "fx3cmd",
279
- type: "fxCommand",
280
- label: "FX3 Command",
281
- description: "3-char command name for table FX slot 3."
282
- },
283
- {
284
- x: 23,
285
- width: 2,
286
- key: "fx3val",
287
- type: "fxValue",
288
- label: "FX3 Value",
289
- description: "Value for table FX3."
290
- }
291
- ]
292
- },
293
- groove: {
294
- title: "Groove View",
295
- type: "grid",
296
- description: "Defines the timing of each phrase step in ticks. Used to create swing, shuffle, triplets, and other rhythmic feels.",
297
- rowField: {
298
- x: 0,
299
- width: 1,
300
- parse: "hex",
301
- type: "rowIndex",
302
- key: "step",
303
- description: "Groove step 0-F. The groove loops when a '--' entry is reached."
304
- },
305
- columns: [{
306
- x: 2,
307
- width: 2,
308
- key: "ticks",
309
- type: "ticks",
310
- label: "Ticks (TIC)",
311
- description: "Number of ticks this step takes. Default is 06 (at 24 PPQN = 1 sixteenth note). '00' skips the step."
312
- }, {
313
- x: 6,
314
- width: 2,
315
- key: "ppq",
316
- type: "ppq",
317
- label: "PPQ",
318
- description: "Pulses Per Quarter note. Only present on groove row 0; absent on all other rows."
319
- }]
320
- },
321
- instrumentpool: {
322
- title: "Instrument Pool",
323
- type: "grid",
324
- description: "Lists all instrument slots with their mix routing. Each row shows the instrument name and its dry/FX send levels.",
325
- rowField: {
326
- x: 0,
327
- width: 2,
328
- parse: "hex",
329
- type: "rowIndex",
330
- key: "instIndex",
331
- description: "Instrument slot index 00-7F."
332
- },
333
- columns: [
334
- {
335
- x: 3,
336
- width: 12,
337
- key: "name",
338
- type: "instrumentName",
339
- label: "Instrument Name",
340
- description: "Name of the instrument in this slot (up to 12 chars). '------------' = empty slot."
341
- },
342
- {
343
- x: 16,
344
- width: 2,
345
- key: "dry",
346
- type: "volume",
347
- label: "Dry (DRY)",
348
- description: "Direct output volume for this instrument (hex 00-FF)."
349
- },
350
- {
351
- x: 19,
352
- width: 2,
353
- key: "mx",
354
- type: "volume",
355
- label: "ModFX (MX)",
356
- description: "ModFX send level (hex 00-FF)."
357
- },
358
- {
359
- x: 22,
360
- width: 2,
361
- key: "de",
362
- type: "volume",
363
- label: "Delay (DE)",
364
- description: "Delay send level (hex 00-FF)."
365
- },
366
- {
367
- x: 25,
368
- width: 2,
369
- key: "rv",
370
- type: "volume",
371
- label: "Reverb (RV)",
372
- description: "Reverb send level (hex 00-FF)."
373
- },
374
- {
375
- x: 28,
376
- width: 2,
377
- key: "eq",
378
- type: "eqSlot",
379
- label: "EQ Slot (EQ)",
380
- description: "EQ slot assignment. '--' = no EQ."
381
- }
382
- ]
383
- }
27
+ rowIndex: "The positional index of this row in the current view (song row, chain position, phrase step, etc.).",
28
+ noteInterval: "Scale row label: one of the 12 note intervals C, C#, D, D#, E, F, F#, G, G#, A, A#, B (sharps use '#', naturals may render a dim '-' pad, e.g. 'C-').",
29
+ onOff: "Toggle field displayed as 'ON' or 'OFF' ('--' = unset). Used by the scale view 'EN' column.",
30
+ semitoneOffset: "Signed semitone offset in decimal notation with two decimals (-24.00 to +24.00), e.g. '00.00', '-00.50', '12.00'. Used by the scale view 'OFFSET' column.",
31
+ swing: "Groove swing amount as a percentage with one decimal, e.g. '50.0%' = straight timing, higher = swung. Only present on groove row 0; absent on all other rows."
384
32
  },
33
+ views: /* @__PURE__ */ JSON.parse("{\"song\":{\"title\":\"Song View\",\"type\":\"grid\",\"description\":\"Arranges chains across 8 independent tracks to form the song structure. Each row is a song position (up to 256 rows); each column is a track. Each track advances vertically until it reaches an empty column ('--'), then loops back to row 00. Chains containing no notes are grayed out; chains '00' or 'FE' are commonly used as silent spacers. On row '00', [UP][UP] enters track reordering mode.\",\"rowField\":{\"x\":0,\"width\":2,\"parse\":\"hex\",\"type\":\"rowIndex\",\"key\":\"songRow\",\"description\":\"Song row 00-FF. Each track loops back to row 00 when it reaches '--'.\"},\"columns\":[{\"x\":3,\"width\":2,\"key\":\"track1\",\"type\":\"chainRef\",\"label\":\"Track 1\",\"meta\":{\"trackIndex\":1}},{\"x\":6,\"width\":2,\"key\":\"track2\",\"type\":\"chainRef\",\"label\":\"Track 2\",\"meta\":{\"trackIndex\":2}},{\"x\":9,\"width\":2,\"key\":\"track3\",\"type\":\"chainRef\",\"label\":\"Track 3\",\"meta\":{\"trackIndex\":3}},{\"x\":12,\"width\":2,\"key\":\"track4\",\"type\":\"chainRef\",\"label\":\"Track 4\",\"meta\":{\"trackIndex\":4}},{\"x\":15,\"width\":2,\"key\":\"track5\",\"type\":\"chainRef\",\"label\":\"Track 5\",\"meta\":{\"trackIndex\":5}},{\"x\":18,\"width\":2,\"key\":\"track6\",\"type\":\"chainRef\",\"label\":\"Track 6\",\"meta\":{\"trackIndex\":6}},{\"x\":21,\"width\":2,\"key\":\"track7\",\"type\":\"chainRef\",\"label\":\"Track 7\",\"meta\":{\"trackIndex\":7}},{\"x\":24,\"width\":2,\"key\":\"track8\",\"type\":\"chainRef\",\"label\":\"Track 8\",\"meta\":{\"trackIndex\":8}}]},\"chain\":{\"title\":\"Chain View\",\"type\":\"grid\",\"description\":\"An ordered list of up to 16 phrases (256 steps). The first '--' phrase ends the chain and the song continues on to the next chain in the song view. The 'TSP' column optionally transposes every note in the phrase in semitones (relative hex).\",\"rowField\":{\"x\":0,\"width\":1,\"parse\":\"hex\",\"type\":\"rowIndex\",\"key\":\"chainPos\",\"description\":\"Position within the chain (0-F, max 16 entries).\"},\"columns\":[{\"x\":2,\"width\":2,\"key\":\"phrase\",\"type\":\"phraseRef\",\"label\":\"Phrase (PH)\",\"description\":\"Phrase number to play at this chain position.\"},{\"x\":5,\"width\":2,\"key\":\"transpose\",\"type\":\"transpose\",\"label\":\"Transpose (TSP)\",\"description\":\"Optional note transpose in semitones applied to every note in the phrase (relative hex).\"}]},\"phrase\":{\"title\":\"Phrase View\",\"type\":\"grid\",\"description\":\"A 16-step sequence. Each step holds a note, velocity, instrument assignment, and up to 3 FX command+value pairs. Notes cover 11 octaves (the full 128 MIDI note range); velocity defaults to 64 (hex); an empty instrument column plays the note without retriggering the instrument. A '*' next to the phrase number indicates the phrase is used elsewhere in the chain or song.\",\"rowField\":{\"x\":0,\"width\":1,\"parse\":\"hex\",\"type\":\"rowIndex\",\"key\":\"step\",\"description\":\"Step index 0-F (16th note by default; altered by groove).\"},\"columns\":[{\"x\":2,\"width\":3,\"key\":\"note\",\"type\":\"note\",\"label\":\"Note (N)\"},{\"x\":6,\"width\":2,\"key\":\"vel\",\"type\":\"velocity\",\"label\":\"Velocity (V)\"},{\"x\":9,\"width\":2,\"key\":\"inst\",\"type\":\"instrumentRef\",\"label\":\"Instrument (I)\"},{\"x\":12,\"width\":3,\"key\":\"fx1cmd\",\"type\":\"fxCommand\",\"label\":\"FX1 Command\"},{\"x\":15,\"width\":2,\"key\":\"fx1val\",\"type\":\"fxValue\",\"label\":\"FX1 Value\"},{\"x\":18,\"width\":3,\"key\":\"fx2cmd\",\"type\":\"fxCommand\",\"label\":\"FX2 Command\"},{\"x\":21,\"width\":2,\"key\":\"fx2val\",\"type\":\"fxValue\",\"label\":\"FX2 Value\"},{\"x\":24,\"width\":3,\"key\":\"fx3cmd\",\"type\":\"fxCommand\",\"label\":\"FX3 Command\"},{\"x\":27,\"width\":2,\"key\":\"fx3val\",\"type\":\"fxValue\",\"label\":\"FX3 Value\"}]},\"table\":{\"title\":\"Table View\",\"type\":\"grid\",\"description\":\"A 16-step mini-sequencer that runs alongside an instrument. Used for arpeggios, multi-stage envelopes, and automated FX. The 'N' column transposes the instrument for the step (relative hex); 'V' multiplies with the phrase-row velocity. Each instrument has a dedicated table plus 128 assignable tables (TBL command). FX columns can run at independent speeds via TIC; a TIC on the last table row affects all rows. HOP shortens or loops the table.\",\"rowField\":{\"x\":0,\"width\":1,\"parse\":\"hex\",\"type\":\"rowIndex\",\"key\":\"step\",\"description\":\"Table step 0-F. Loops from bottom unless a HOP command redirects.\"},\"columns\":[{\"x\":2,\"width\":2,\"key\":\"transpose\",\"type\":\"transpose\",\"label\":\"Transpose (N)\",\"description\":\"Transposes the instrument for this step (relative hex). '--' = no transpose.\"},{\"x\":5,\"width\":2,\"key\":\"volume\",\"type\":\"volume\",\"label\":\"Volume (V)\",\"description\":\"Volume multiplier applied on top of the phrase velocity (hex). '--' = no override.\"},{\"x\":8,\"width\":3,\"key\":\"fx1cmd\",\"type\":\"fxCommand\",\"label\":\"FX1 Command\",\"description\":\"3-char command name for table FX slot 1.\"},{\"x\":11,\"width\":2,\"key\":\"fx1val\",\"type\":\"fxValue\",\"label\":\"FX1 Value\",\"description\":\"Value for table FX1.\"},{\"x\":14,\"width\":3,\"key\":\"fx2cmd\",\"type\":\"fxCommand\",\"label\":\"FX2 Command\",\"description\":\"3-char command name for table FX slot 2.\"},{\"x\":17,\"width\":2,\"key\":\"fx2val\",\"type\":\"fxValue\",\"label\":\"FX2 Value\",\"description\":\"Value for table FX2.\"},{\"x\":20,\"width\":3,\"key\":\"fx3cmd\",\"type\":\"fxCommand\",\"label\":\"FX3 Command\",\"description\":\"3-char command name for table FX slot 3.\"},{\"x\":23,\"width\":2,\"key\":\"fx3val\",\"type\":\"fxValue\",\"label\":\"FX3 Value\",\"description\":\"Value for table FX3.\"}]},\"groove\":{\"title\":\"Groove View\",\"type\":\"grid\",\"description\":\"Defines the timing of each phrase step in ticks. Used to create swing, shuffle, triplets, and other rhythmic feels. At the default 24 PPQ a step is 6 ticks and a full phrase totals 96 ticks. The groove loops when a '--' entry is reached; a '00' entry skips the phrase step. Row 0 also holds the PPQ resolution (24/48/96/192) and the SWING percentage; editing the row 0 tick value alters rows 0 and 1 together (a common swing setting is 07,05 or 08,04).\",\"rowField\":{\"x\":0,\"width\":1,\"parse\":\"hex\",\"type\":\"rowIndex\",\"key\":\"step\",\"description\":\"Groove step 0-F. The groove loops when a '--' entry is reached.\"},\"columns\":[{\"x\":2,\"width\":2,\"key\":\"ticks\",\"type\":\"ticks\",\"label\":\"Ticks (TIC)\",\"description\":\"Number of ticks this step takes. Default is 06 (at 24 PPQN = 1 sixteenth note). '00' skips the step.\"},{\"x\":6,\"width\":2,\"key\":\"ppq\",\"type\":\"ppq\",\"label\":\"PPQ\",\"description\":\"Pulses Per Quarter note: 24, 48, 96 or 192. Only present on groove row 0; absent on all other rows.\"},{\"x\":10,\"width\":5,\"key\":\"swing\",\"type\":\"swing\",\"label\":\"Swing\",\"description\":\"Swing amount as a percentage (e.g. '50.0%' = straight). Only present on groove row 0; absent on all other rows.\"}]},\"scale\":{\"title\":\"Scale View\",\"type\":\"grid\",\"description\":\"Defines and quantizes note-related events (project/chain transpose, note entry, ARP, PIT, and the MIDIOUT instrument CHD and ADD commands). Up to 16 user-defined scales per project; scale '00' is the default for all 8 tracks and can be overridden per track with SCA/SCG FX commands. Each of the 12 note intervals can be enabled ('EN' = ON) with an optional detuning offset (-24.00 to +24.00 semitones). Rows below the 12 intervals (not column-mapped) hold: KEY (global root note for the default scale), TUNE (A4 reference in Hz, e.g. '440.00'), NAME (up to 16 characters, 92 factory scales load from /Scales/Factory), and the LOAD/SAVE actions.\",\"columns\":[{\"x\":0,\"width\":2,\"key\":\"interval\",\"type\":\"noteInterval\",\"label\":\"Note Interval\",\"description\":\"Note interval row label: C, C#, D, D#, E, F, F#, G, G#, A, A#, B.\"},{\"x\":3,\"width\":3,\"key\":\"en\",\"type\":\"onOff\",\"label\":\"Enabled (EN)\",\"description\":\"Enables this note interval in the scale: 'ON' or 'OFF' ('--' = unset).\"},{\"x\":6,\"width\":6,\"key\":\"offset\",\"type\":\"semitoneOffset\",\"label\":\"Offset (OFFSET)\",\"description\":\"Detune offset in semitones, decimal with two decimals (-24.00 to +24.00), e.g. '00.00'.\"}]},\"instrumentpool\":{\"title\":\"Instrument Pool\",\"type\":\"grid\",\"description\":\"Lists all 128 instrument slots with their mix routing. Each row shows the instrument name (up to 12 chars, '------------' = empty slot) and its dry/FX send levels. Mixer-related settings can be adjusted per instrument here; [EDIT] on an empty slot loads an instrument or sample.\",\"rowField\":{\"x\":0,\"width\":2,\"parse\":\"hex\",\"type\":\"rowIndex\",\"key\":\"instIndex\",\"description\":\"Instrument slot index 00-7F.\"},\"columns\":[{\"x\":3,\"width\":12,\"key\":\"name\",\"type\":\"instrumentName\",\"label\":\"Instrument Name\",\"description\":\"Name of the instrument in this slot (up to 12 chars). '------------' = empty slot.\"},{\"x\":16,\"width\":2,\"key\":\"dry\",\"type\":\"volume\",\"label\":\"Dry (DRY)\",\"description\":\"Direct output volume for this instrument (hex 00-FF).\"},{\"x\":19,\"width\":2,\"key\":\"mx\",\"type\":\"volume\",\"label\":\"ModFX (MX)\",\"description\":\"ModFX send level (hex 00-FF).\"},{\"x\":22,\"width\":2,\"key\":\"de\",\"type\":\"volume\",\"label\":\"Delay (DE)\",\"description\":\"Delay send level (hex 00-FF).\"},{\"x\":25,\"width\":2,\"key\":\"rv\",\"type\":\"volume\",\"label\":\"Reverb (RV)\",\"description\":\"Reverb send level (hex 00-FF).\"},{\"x\":28,\"width\":2,\"key\":\"eq\",\"type\":\"eqSlot\",\"label\":\"EQ Slot (EQ)\",\"description\":\"EQ slot assignment. '--' = no EQ.\"}]},\"inst\":{\"title\":\"Instrument View\",\"type\":\"parameter\",\"description\":\"Per-instrument parameters for the selected slot: TYPE (Wavsynth, Macrosynth, Sampler, FM Synth, Hypersynth, External Instrument, MIDI Out), LOAD/SAVE presets, NAME, TRANSP. (enable/disable transposition from scales and transpose columns), TABLE TIC (default table speed), and EQ slot, plus the synth engine parameters. Almost every parameter has an associated FX command; highlighting a parameter and navigating to the phrase or table view sets that parameter's FX command as default.\"},\"instmods\":{\"title\":\"Instrument Modulation View\",\"type\":\"parameter\",\"description\":\"Four configurable modulation slots per instrument: AHD envelope, ADSR envelope, DRUM envelope, LFO, TRIG envelope, or TRACKING, each with a destination parameter (DEST) and optional source (SRC).\"},\"mixer\":{\"title\":\"Mixer View\",\"type\":\"parameter\",\"description\":\"Mix levels for the 8 tracks, the 3 send effects (MX/DE/RE), the analog input (INPUT, with dual-mono mode) and USB input, the DJ filter (DJF), OTT compression, main EQ, limiter (LIM) and main volume (MIX). All signals are summed through OTT, main EQ, limiter, DJ filter and main volume. Most values are also exposed as FX commands (VMV, VMX, VDE, VRE, VT1-8, DJC/DJR/DJT, IVO/IMX/IDE/IRV, USB, ...).\"},\"project\":{\"title\":\"Project View\",\"type\":\"parameter\",\"description\":\"Song-wide settings such as tempo, project transpose (identical to the TSP FX command), and LIVE QUANTIZE behavior for cueing tracks in live mode. [SHIFT]+[OPTION] stores a song snapshot; [SHIFT]+[EDIT] recalls it.\"},\"effectsettings\":{\"title\":\"Effect Settings View\",\"type\":\"parameter\",\"description\":\"Settings for the 3 send effects: ModFX type/depth/frequency/width, Delay time/feedback/width, and Reverb size/decay/modulation/width/freeze — all addressable via the XMT-XMW, XDT-XDR and XRS-XRZ FX commands.\"},\"mixeq\":{\"title\":\"Mix EQ View\",\"type\":\"parameter\",\"description\":\"EQ editor for the main mix EQ slot (assign with the EQM FX command). Selecting EQ in the Mixer view and pressing [EDIT] or [SHIFT]+[RIGHT] opens this view.\"},\"modfxeq\":{\"title\":\"ModFX EQ View\",\"type\":\"parameter\",\"description\":\"EQ editor for the ModFX send path.\"},\"delayeq\":{\"title\":\"Delay EQ View\",\"type\":\"parameter\",\"description\":\"EQ editor for the Delay send path.\"},\"reverbeq\":{\"title\":\"Reverb EQ View\",\"type\":\"parameter\",\"description\":\"EQ editor for the Reverb send path.\"},\"mixscope\":{\"title\":\"Mix Scope View\",\"type\":\"parameter\",\"description\":\"Graphical scope of the main mix activity. Opened from the Mixer view with MIX selected via [EDIT] or [SHIFT]+[RIGHT].\"},\"limiterscope\":{\"title\":\"Limiter Scope View\",\"type\":\"parameter\",\"description\":\"Graphical scope of the limiter's compression activity (the white line on the MIX indicator). Opened from the Mixer view with LIM selected via [EDIT] or [SHIFT]+[RIGHT].\"},\"systemsettings\":{\"title\":\"System Settings View\",\"type\":\"parameter\",\"description\":\"System-level settings for the device.\"},\"loadinstrument\":{\"title\":\"Load Instrument\",\"type\":\"parameter\",\"description\":\"File browser for loading an instrument preset from the SD card ([EDIT] on an empty instrument slot, or LOAD in the Instrument view).\"},\"selectsavedirectory\":{\"title\":\"Select Save Directory\",\"type\":\"parameter\",\"description\":\"File browser directory-selection step when saving a preset or project.\"},\"createdirectory\":{\"title\":\"Create Directory\",\"type\":\"parameter\",\"description\":\"File browser dialog for creating a new directory on the SD card.\"}}"),
385
34
  fxCommands: {
386
35
  sequencer: {
387
36
  ARP: { description: "Arpeggio: plays 3 notes rapidly. X=first interval semitones, Y=second interval semitones." },
388
37
  ARC: { description: "Arpeggio Config: X=mode, Y=speed in ticks." },
389
- CHA: { description: "Chance: X=probability left of command (0=never, F=always), Y=probability right." },
38
+ CHA: { description: "Chance: X=probability left of command (0=never, F=always), Y=probability right. In a table: probability for everything to the left of CHA from 00 (never) to FF (always)." },
390
39
  DEL: { description: "Delay: in phrase delays entire row by XX ticks; in table delays table playhead." },
391
40
  GRV: { description: "Groove: sets groove number XX for the current track." },
392
41
  GGR: { description: "Global Groove: sets groove XX for all tracks." },
@@ -394,9 +43,9 @@ var r = {
394
43
  INS: { description: "Instrument: changes active instrument to XX as an FX command." },
395
44
  KIL: { description: "Kill: stops the playing instrument after XX ticks." },
396
45
  RND: { description: "Random: randomises the preceding FX command. X=left range, Y=right range (0=none, F=full)." },
397
- RNL: { description: "Randomise Left: randomises the FX command to the left." },
46
+ RNL: { description: "Randomise Left: randomises the FX command to the left (X=left range, Y=right range). In the first column RNL randomises the note and instrument number in phrase, or note and velocity in table." },
398
47
  RET: { description: "Retrig: retriggers current row. Y≠0: retrig every Y ticks with X volume ramp. Y=0: single retrig after X ticks." },
399
- REP: { description: "Repeat: repeats and increments the last FX command by XX each step." },
48
+ REP: { description: "Repeat: repeats and increments the last FX command by XX each step. Active until a new command or REP00 stops it; it does not need to appear on every row. A double-caret '^^' appears next to an FX lane while a REP from a previous phrase is active." },
400
49
  RTO: { description: "Repeat To: sets the min/max value that REP stops at." },
401
50
  RMX: { description: "Remix: repositions the phrase playhead (Y) on tracks to the left (selected by X)." },
402
51
  NTH: { description: "Nth Trigger: conditional trigger based on loop count." },
@@ -406,17 +55,17 @@ var r = {
406
55
  PVX: { description: "Extreme Vibrato: like PVB but with higher range." },
407
56
  SCA: { description: "Track Scale: X=key signature, Y=scale number for this track." },
408
57
  SCG: { description: "Global Scale: X=key, Y=scale number for the whole song." },
409
- SNG: { description: "Song Hop: moves this track's song position by XX rows relative to current." },
58
+ SNG: { description: "Song Hop: moves this track's song position by XX rows relative to current. Ignored if the resulting song position is not playable." },
410
59
  SED: { description: "Random Seed: sets the random seed XX for this track." },
411
60
  TBL: { description: "Table: assigns table number XX to the current instrument." },
412
61
  THO: { description: "Table Hop: jumps all table columns to position 0X." },
413
- TIC: { description: "Table Tick: sets the table tick rate. In a table, each FX column can run independently." },
414
- TBX: { description: "Aux Table: runs table XX in parallel with the instrument table. 00=stop aux table." },
62
+ TIC: { description: "Table Tick: sets the table tick rate. 00 = increment row on each instrument trigger; 01-FB = ticks per row; FC = Octave Map (playing octave maps to table row); FD = Velocity Map; FE = Note Map (pair with HOP00 on row 0C to limit to 12 notes/octave); FF = increment at 200 Hz. In a table each FX column can run independently; a TIC on the last table row affects all rows." },
63
+ TBX: { description: "Aux Table: runs table XX in parallel with the instrument table. 00=stop aux table. A TIC in the same row as a TBX affects the auxiliary table's tick rate." },
415
64
  TPO: { description: "Tempo: sets song BPM to XX (hex → decimal conversion shown in help text)." },
416
- TSP: { description: "Global Transpose: transposes the entire song by XX semitones." },
417
- NXT: { description: "Next Track Trigger: plays instrument XX on the next track using current note/velocity." },
65
+ TSP: { description: "Global Song Transpose: transposes the entire song by XX semitones. Identical to the transpose value in the Project View." },
66
+ NXT: { description: "Next Track Trigger: plays instrument XX on the track to the right using the current note/velocity. Does not work on track 8." },
418
67
  OFF: { description: "Note Off: stops the playing instrument after XX ticks. Triggers ADSR release stage." },
419
- MTT: { description: "Micro Time: adjusts row playback timing in sub-tick (1/8 tick) amounts." }
68
+ MTT: { description: "Micro Time: adjusts row playback timing in positive or negative sub-tick (1/8 tick) amounts. Negative amounts do not work on the first phrase row. Currently has no action in tables." }
420
69
  },
421
70
  instrument: {
422
71
  VOL: { description: "Volume offset (relative)." },
@@ -437,7 +86,9 @@ var r = {
437
86
  LF1: { description: "LFO 1 Frequency offset." },
438
87
  LF2: { description: "LFO 2 Frequency offset." },
439
88
  LT1: { description: "Retrigger LFO 1 (value sets phase offset)." },
440
- LT2: { description: "Retrigger LFO 2." }
89
+ LT2: { description: "Retrigger LFO 2." },
90
+ CHD: { description: "Chord (MIDIOUT instrument): triggers a chord. Quantized by the active scale." },
91
+ ADD: { description: "Add Note (MIDIOUT instrument): adds a note to the chord. Quantized by the active scale." }
441
92
  },
442
93
  mixer: {
443
94
  VMV: { description: "Main Volume: sets the main song output volume." },
@@ -456,7 +107,32 @@ var r = {
456
107
  DJR: { description: "DJ Filter Resonance." },
457
108
  DJT: { description: "DJ Filter Type." },
458
109
  EQM: { description: "Assign main mix EQ slot." },
459
- EQI: { description: "Assign current instrument EQ slot." }
110
+ EQI: { description: "Assign current instrument EQ slot." },
111
+ XMT: { description: "Send Effect: ModFX mod type and phase position (Effect Settings view)." },
112
+ XMM: { description: "Send Effect: ModFX mod depth (Effect Settings view)." },
113
+ XMF: { description: "Send Effect: ModFX mod frequency (Effect Settings view)." },
114
+ XMW: { description: "Send Effect: ModFX stereo width (Effect Settings view)." },
115
+ XMR: { description: "Send Effect: ModFX to reverb mix (Effect Settings view)." },
116
+ XDT: { description: "Send Effect: Delay time — X = left, Y = right, in large increments (Effect Settings view)." },
117
+ XDF: { description: "Send Effect: Delay feedback (Effect Settings view)." },
118
+ XDW: { description: "Send Effect: Delay stereo width (Effect Settings view)." },
119
+ XDR: { description: "Send Effect: Delay to reverb mix (Effect Settings view)." },
120
+ XRS: { description: "Send Effect: Reverb room size (Effect Settings view)." },
121
+ XRD: { description: "Send Effect: Reverb decay (Effect Settings view)." },
122
+ XRM: { description: "Send Effect: Reverb mod depth (Effect Settings view)." },
123
+ XRF: { description: "Send Effect: Reverb mod frequency (Effect Settings view)." },
124
+ XRW: { description: "Send Effect: Reverb stereo width (Effect Settings view)." },
125
+ XRZ: { description: "Send Effect: Reverb freeze — enabled with a value greater than 00, disabled at 00." },
126
+ IVO: { description: "Line Input Mixer: analog input volume (Mixer view)." },
127
+ IMX: { description: "Line Input Mixer: analog input ModFX send (Mixer view)." },
128
+ IDE: { description: "Line Input Mixer: analog input delay send (Mixer view)." },
129
+ IRV: { description: "Line Input Mixer: analog input reverb send (Mixer view). Also referenced as 'IRE' in the manual text." },
130
+ IRE: { description: "Alias of IRV: analog input reverb send (Mixer view)." },
131
+ IV2: { description: "Line Input Mixer: volume for the 2nd input (right channel in dual-mono input mode, set in the Mixer view)." },
132
+ IM2: { description: "Line Input Mixer: ModFX send for the 2nd input (right channel in dual-mono input mode)." },
133
+ ID2: { description: "Line Input Mixer: delay send for the 2nd input (right channel in dual-mono input mode)." },
134
+ IR2: { description: "Line Input Mixer: reverb send for the 2nd input (right channel in dual-mono input mode)." },
135
+ USB: { description: "USB input volume (Mixer view)." }
460
136
  }
461
137
  }
462
138
  }, i = r.fxCommands;
@@ -573,14 +249,14 @@ function h(e) {
573
249
  activeField: null
574
250
  };
575
251
  let { line: h, offset: g } = d(l), _ = e.cursorPos ? e.cursorPos.x - g : 0, v = n.rowField ? p(h, n.rowField) : null, y = {};
576
- for (let e of n.columns) y[e.key] = f(e, h);
252
+ for (let e of n.columns ?? []) y[e.key] = f(e, h);
577
253
  let b = {
578
254
  rowIndex: v,
579
255
  rowKey: n.rowField?.key ?? "row",
580
256
  fields: y
581
257
  }, x = null;
582
258
  if (e.cursorPos) {
583
- let e = m(n.columns, _);
259
+ let e = m(n.columns ?? [], _);
584
260
  if (e) {
585
261
  let n = y[e.key];
586
262
  n && (x = {
@@ -639,6 +315,8 @@ function _(e) {
639
315
  case "fxValue": return e.hexValue == null ? e.rawValue : `${e.rawValue}h (dec ${e.hexValue})`;
640
316
  case "ticks": return e.rawValue === "00" ? "00 (skip step)" : e.hexValue == null ? e.rawValue : `${e.rawValue}h (${e.hexValue} ticks)`;
641
317
  case "volume": return e.rawValue;
318
+ case "noteInterval": return `Interval ${e.rawValue}`;
319
+ case "semitoneOffset": return e.isEmpty ? "(empty)" : `${e.rawValue} st`;
642
320
  default: return e.rawValue;
643
321
  }
644
322
  }