@yam8d/m8-sdk 0.5.6 → 0.5.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yam8d/m8-sdk",
3
- "version": "0.5.6",
3
+ "version": "0.5.7",
4
4
  "description": "Client SDK for apps that read and drive a Dirtywave M8, inside a yam8d External Apps iframe or standalone over Web Serial, WebUSB or Web MIDI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -3,7 +3,12 @@
3
3
  *
4
4
  * Explains what an FX value does and follows FX "lanes" (FX1/FX2/FX3 columns)
5
5
  * down a phrase, so a REP command - or an empty cell sitting under one - can be
6
- * described in terms of the command it is repeating.
6
+ * described in terms of the command it shifts.
7
+ *
8
+ * REP does not type the command above it again: it shifts the value that command
9
+ * computed, on every row, by its own value counted in quarters (01 = +0.25,
10
+ * 04 = +1, FC = -1). The value stops at 00 and FF, or at the RTO value (absolute);
11
+ * it never wraps.
7
12
  *
8
13
  * Purely structural: works on already-parsed cells, no dependency on viewContext.
9
14
  */
@@ -28,7 +33,7 @@ export type FxLaneEvent =
28
33
  | 'replace'
29
34
  /** REP XX (XX>0) starts repeating. */
30
35
  | 'rep'
31
- /** REP XX while another REP was already running (new increment). */
36
+ /** REP XX while another REP was already running (new step). */
32
37
  | 'repChange'
33
38
  /** REP 00 stops the repeat. */
34
39
  | 'repStop'
@@ -36,7 +41,7 @@ export type FxLaneEvent =
36
41
  | 'orphan'
37
42
  /** RTO sets the limit for the running REP. */
38
43
  | 'rto'
39
- /** Empty cell while a REP is active: the repeated command fires again. */
44
+ /** Empty cell while a REP is active: the value is shifted once more. */
40
45
  | 'continue';
41
46
  export interface M8FxLaneTrace {
42
47
  /** FX lane, 1-3. */
@@ -52,13 +57,25 @@ export interface M8FxLaneTrace {
52
57
  } | null;
53
58
  /** True when a REP is running after this step. */
54
59
  active: boolean;
55
- /** Per-step increment of the running REP (0x01-0xFF, 0x80+ = negative). */
60
+ /** The running REP's step as typed (0x01-0x7F up, 0x80-0xFF down), in quarters: 04 = +1 per row. */
56
61
  increment: number | null;
57
- /** Value set with RTO, if any. */
62
+ /** Value set with RTO, if any: an absolute value, not a shift. */
58
63
  limit: number | null;
59
- /** Value the repeated command has at this step (null when unknown). */
64
+ /**
65
+ * Value of the command at this step while a REP runs, whole part (00-FF). Null for a
66
+ * relative command (the instrument's own value is not on this screen: see `offset`),
67
+ * and when unknown.
68
+ */
60
69
  value: number | null;
61
- /** True when `value` was clamped by the RTO limit. */
70
+ /**
71
+ * While a REP runs on a relative command: how far the parameter is from the instrument's
72
+ * own value (the command's signed value plus the REP's steps; 0.25 units). The stop at
73
+ * 00, FF or the RTO value is not applied, since the instrument's value is unknown here.
74
+ */
75
+ offset: number | null;
76
+ /** Why the REP no longer moves `value`: it reached FF, 00 or the RTO value. */
77
+ held: 'max' | 'min' | 'limit' | null;
78
+ /** True when `value` is held at the RTO value. */
62
79
  atLimit: boolean;
63
80
  /** Step where the running REP began. */
64
81
  repStartStep: number | null;
@@ -66,8 +83,14 @@ export interface M8FxLaneTrace {
66
83
  carried: boolean;
67
84
  }
68
85
  export declare const hex2: (n: number) => string;
69
- /** Hex text of a value, with its signed reading when the command is relative and negative. */
86
+ /** Signed decimal reading of a relative value: 70 -> '+112', F0 -> '−16', 00 -> '±0'. */
87
+ export declare const formatSignedFxValue: (value: number) => string;
88
+ /** Hex text of a value, with its signed decimal reading when the command is relative: '70 (+112)', 'F0 (−16)'. */
70
89
  export declare function formatFxValue(cmd: string, value: number): string;
90
+ /** A REP value in quarters: 00-7F up, 80-FF down. */
91
+ export declare const repStepQuarters: (step: number) => number;
92
+ /** A REP value as the decimal step it is: 01 -> '+0.25', 04 -> '+1', FC -> '−1'. */
93
+ export declare function formatRepStep(step: number): string;
71
94
  export interface FxValueContext {
72
95
  /** Note on the same step (used by ARP to spell out the notes). */
73
96
  note?: string | null;
@@ -85,9 +108,9 @@ export declare function describeFxValue(cmd: string, value: number, ctx?: FxValu
85
108
  * Walks FX lane `lane` (1-3) from step 0 to `step` and reports what is in effect
86
109
  * there. `rows` must hold every step of the phrase, index = step.
87
110
  *
88
- * Model (manual: "Repeat"): REP XX repeats the lane's last command with its value
89
- * bumped by XX on each step, keeps going through empty cells, and stops on a new
90
- * command or REP00. RTO XX in the same lane sets the value REP stops at.
111
+ * Model: REP XX shifts the value the lane's last command computed by XX quarters on
112
+ * each row (its own row included), keeps going through empty cells, and stops on a
113
+ * new command or REP00. RTO XX in the same lane sets the absolute value it stops at.
91
114
  * `carriedIn` says a REP from a previous phrase is running (the '^^' marker).
92
115
  */
93
116
  export declare function analyzeFxLane(rows: FxStepRow[], lane: number, step: number, carriedIn?: boolean): M8FxLaneTrace;
@@ -102,15 +125,15 @@ export declare function describeFxLane(t: M8FxLaneTrace): string | null;
102
125
  */
103
126
  export interface M8RelativeFxState {
104
127
  cmd: string;
105
- /** Net change applied to the parameter (signed; the device clamps to the parameter's range). */
128
+ /** Net change applied to the parameter (signed, in 0.25 units when a REP is involved; the device stops at the parameter's range). */
106
129
  total: number;
107
- /** Times the command was applied (REP-driven repeats included). */
130
+ /** Rows that moved the parameter (the rows of a running REP included). */
108
131
  count: number;
109
132
  /** Step of the last trigger that reset it, or null when none happened in this phrase. */
110
133
  resetStep: number | null;
111
134
  /** What reset it: a row with an instrument number in the I column, or a RET command. */
112
135
  resetBy: 'instrument' | 'ret' | null;
113
- /** True when some of the applications came from a running REP. */
136
+ /** True when some of the change came from a running REP. */
114
137
  viaRep: boolean;
115
138
  }
116
139
  /**
@@ -125,7 +148,8 @@ export declare function relativeResetBy(row: FxStepRow): M8RelativeFxState['rese
125
148
  * value (01-7F) or subtracts it (80-FF) from the instrument's parameter, and the change
126
149
  * stays until a note is triggered with a RET command or with an instrument number in
127
150
  * the I column, which puts every parameter back to the instrument's assigned value.
128
- * A row that triggers resets first, then applies its own commands. State from a
151
+ * A row that triggers resets first, then applies its own commands. A REP under a
152
+ * relative command adds its own step (in quarters) on each row. State from a
129
153
  * previous phrase isn't visible, so totals only cover this phrase.
130
154
  */
131
155
  export declare function analyzeRelativeFx(rows: FxStepRow[], step: number, carriedLane?: number | null): Record<string, M8RelativeFxState>;