@audiofab-io/fv1-core 0.6.0 → 0.6.1

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.
Files changed (61) hide show
  1. package/blocks/ATL_DEVELOPER_REFERENCE.md +156 -156
  2. package/blocks/control/constant.atl +36 -36
  3. package/blocks/control/entropy_lfo.atl +74 -74
  4. package/blocks/control/envelope.atl +120 -120
  5. package/blocks/control/invert.atl +33 -33
  6. package/blocks/control/pot.atl +149 -149
  7. package/blocks/control/power.atl +76 -76
  8. package/blocks/control/ramp_lfo.atl +122 -122
  9. package/blocks/control/scale_offset.atl +84 -84
  10. package/blocks/control/sincos_lfo.atl +126 -126
  11. package/blocks/control/smoother.atl +48 -48
  12. package/blocks/control/tremolizer.atl +54 -54
  13. package/blocks/effects/delay/micro_stutter.atl +77 -77
  14. package/blocks/effects/delay/mn3011.atl +280 -280
  15. package/blocks/effects/delay/simple_delay.atl +96 -96
  16. package/blocks/effects/delay/triple_tap_delay.atl +176 -176
  17. package/blocks/effects/lo-fi/bit_mangler.atl +74 -74
  18. package/blocks/effects/lo-fi/chiptune.atl +311 -311
  19. package/blocks/effects/lo-fi/tape_degrade.atl +181 -181
  20. package/blocks/effects/modulation/chorus.atl +141 -141
  21. package/blocks/effects/modulation/chorus_4voice.atl +188 -188
  22. package/blocks/effects/modulation/flanger.atl +184 -184
  23. package/blocks/effects/modulation/harmonic_trem.atl +129 -129
  24. package/blocks/effects/modulation/phaser.atl +299 -299
  25. package/blocks/effects/pitch/octave_up_down.atl +80 -80
  26. package/blocks/effects/pitch/pitch_offset.atl +149 -149
  27. package/blocks/effects/pitch/pitch_offset_dual.atl +197 -197
  28. package/blocks/effects/pitch/pitch_shift.atl +115 -115
  29. package/blocks/effects/pitch/sub_octave.atl +100 -100
  30. package/blocks/effects/reverb/ducking_reverb.atl +145 -145
  31. package/blocks/effects/reverb/min_reverb.atl +132 -132
  32. package/blocks/effects/reverb/plate_reverb.atl +344 -344
  33. package/blocks/effects/reverb/room_reverb.atl +293 -293
  34. package/blocks/effects/reverb/smear.atl +90 -90
  35. package/blocks/effects/reverb/spring_reverb.atl +353 -353
  36. package/blocks/filter/1p_high_pass.atl +62 -62
  37. package/blocks/filter/1p_low_pass.atl +58 -58
  38. package/blocks/filter/auto_wah.atl +207 -207
  39. package/blocks/filter/bbd_loss.atl +79 -79
  40. package/blocks/filter/shelving_high_pass.atl +76 -76
  41. package/blocks/filter/shelving_low_pass.atl +76 -76
  42. package/blocks/filter/svf_2p.atl +116 -116
  43. package/blocks/gain_mix/crossfade.atl +93 -93
  44. package/blocks/gain_mix/crossfade2.atl +86 -86
  45. package/blocks/gain_mix/crossfade3.atl +71 -71
  46. package/blocks/gain_mix/gainboost.atl +54 -54
  47. package/blocks/gain_mix/mixer2.atl +76 -76
  48. package/blocks/gain_mix/mixer3.atl +109 -109
  49. package/blocks/gain_mix/mixer4.atl +151 -151
  50. package/blocks/gain_mix/volume.atl +50 -50
  51. package/blocks/io/adc.atl +53 -53
  52. package/blocks/io/dac.atl +61 -61
  53. package/blocks/other/stickynote.atl +24 -24
  54. package/blocks/other/tone_gen_adjustable.atl +137 -137
  55. package/blocks/other/tone_gen_fixed.atl +109 -109
  56. package/dist/blockDiagram/builtinBlocks.js +107 -107
  57. package/dist/blockDiagram/builtinBlocks.js.map +1 -1
  58. package/dist/blockDiagram/compiler/BlockTemplate.d.ts.map +1 -1
  59. package/dist/blockDiagram/compiler/BlockTemplate.js +18 -0
  60. package/dist/blockDiagram/compiler/BlockTemplate.js.map +1 -1
  61. package/package.json +2 -2
@@ -1,156 +1,156 @@
1
- # ATL (Audiofab Template Language) Block Development Reference
2
-
3
- This document serves as the foundational context and ruleset for creating high-quality FV-1 algorithms as ATL blocks in the FV-1 VS Code Extension.
4
-
5
- ## 1. File Structure Overview
6
- Each `.atl` file must consist of two main parts separated by `---`:
7
- 1. **JSON Configuration Module**: Defines block metadata, inputs, outputs, parameters, memories, and hardware registers.
8
- 2. **ATL Code Module**: Contains the FV-1 DSP assembly mixed with ATL macros and directives.
9
-
10
- ## 2. Parameter Conversions
11
- All parameters should be explicitly mapped using proper conversions. Use the `conversion` key in the parameter JSON.
12
- - **Gain**: Use `"conversion": "DBLEVEL"` (UI shows dB, code gets linear).
13
- - **Delay Times**: Use `"conversion": "MS_TO_SAMPLES"` (UI shows ms, code gets sample count).
14
- - **Frequencies / Rates**: Use `"conversion": "HZ_TO_LFO_RATE"` for LFOs, `"conversion": "LOGFREQ"` for filters.
15
- - **LFO Width**: Use `"conversion": "MS_TO_LFO_RANGE"`.
16
-
17
- ## 3. Fallbacks for Control Inputs
18
- Every control input must have a corresponding "fallback" strategy when the input pin is NOT connected by the user.
19
-
20
- ### The `@cv` Macro (Recommended)
21
- The standard way to handle control inputs is using the `@cv` macro. It automatically handles three scenarios based on whether the input port is connected:
22
- 1. **Unconnected**: Loads the value of the port's associated parameter as a constant (`SOF 0.0, <equ>`).
23
- 2. **Connected to a standard CV/LFO**: Loads the parameter value and scales it by the pot input (`CLR; SOF 0.0, <equ>; MULX <reg>`), giving ACC ∈ [0..paramValue].
24
- 3. **Connected to a zero-bypassed Pot**: Uses the 5-instruction bypass block with the pot's `Zero Bypass Value` as the fallback (instead of the parameter). The pot value is scaled by the parameter value via `RDAX reg, <equ>`.
25
-
26
- The control input JSON **must** include a `"parameter"` field pointing to the parameter that provides the default/range:
27
-
28
- ```json
29
- { "id": "mixCV", "name": "Mix", "type": "control", "required": false, "parameter": "mix" }
30
- ```
31
-
32
- Usage in the ATL template body — just one line:
33
-
34
- ```assembly
35
- ; ACC now holds the correct value (constant or pot-scaled)
36
- @cv mixCV
37
- ```
38
-
39
- ### The `@mulcv` Macro — Scale existing ACC by CV
40
- Use `@mulcv` when ACC already contains a signal you want to **multiply** by the CV value, without clearing first.
41
-
42
- | Port state | Generated assembly | Instructions |
43
- |---|---|---|
44
- | Unconnected | `SOF paramValue, 0.0` | 1 |
45
- | Connected | `SOF paramValue, 0.0; MULX reg` | 2 |
46
- | Zero-bypassed | `WRAX scratch; RDAX reg, equ; bypass; MULX scratch` | 7 |
47
-
48
- Example — applying a mix CV to a difference signal:
49
- ```assembly
50
- rdax ${reg.mix_dry}, -1.0 ; ACC = wet - dry
51
- @mulcv mixCV ; ACC = (wet - dry) * mix
52
- rdax ${reg.mix_dry}, 1.0 ; ACC = (wet - dry) * mix + dry
53
- ```
54
-
55
- ### Legacy `@if pinConnected` Method
56
- If you need highly custom logic between bypassed vs active states, you can still manually check if the pin is connected. Note that this method *does not* support the Zero-Bypassed Pot feature natively:
57
-
58
- ```assembly
59
- @if pinConnected(mixCV)
60
- rdax ${input.mixCV}, 1.0
61
- @else
62
- sof 0.0, ${mix}
63
- @endif
64
- ```
65
-
66
- ## 4. Input Connection Safeguards
67
- If the block's main audio input pin is completely disconnected, the block should generally produce no instructions, or handle the bypass effectively, avoiding generating useless cycles.
68
-
69
- ```assembly
70
- @section main
71
- @if pinConnected(input)
72
- ; ... heavy processing ...
73
- @else
74
- ; Block disabled / bypassed
75
- @endif
76
- ```
77
-
78
- ## 5. Memory Management
79
- Delay block memory allocations MUST be explicitly placed in the `"memories"` JSON array.
80
- - A fixed size: `{ "id": "pdel", "size": 3276 }`
81
- - Bound to a parameter (e.g., `delayLength` converted by `MS_TO_SAMPLES`): `{ "id": "delayl", "size": "delayLength" }`
82
-
83
- In code, reference these with `${mem.pdel}` or `${mem.delayl}`.
84
- - To access base address: `${mem.id}`
85
- - To access fractional taps or offset taps: `${mem.id} + offset`
86
-
87
- ## 6. Registers
88
- All registers used by the block must be declared in the `"registers"` JSON array.
89
- Reference them via `${reg.registryName}`. No magic EQU offsets/allocations should be done manually for registers.
90
- Example: `"registers": ["wet", "dry", "temp"]`
91
-
92
- ## 7. Magic Numbers & Reusability
93
- Avoid magic constants scattered throughout the assembly. Declare them using `@equals` in an `@section header`.
94
- ```assembly
95
- @section header
96
- @equals decayLimit 0.8
97
- @equals bandwidth 0.31852
98
- ```
99
- To calculate derived parameters, use `EQU` formulas if needed, e.g.:
100
- ```assembly
101
- EQU tap1 (0.9 * ${tap1Center} * ${delayLength})
102
- ```
103
-
104
- ## 8. Routing / I/O Defaults
105
- If left and right outputs exist, verify which are connected to prevent writing to address zero (`ADDR_PTR` trick or just skipping) if the output isn't used:
106
- ```assembly
107
- @if pinConnected(outL)
108
- wrax ${output.outL}, 0.0
109
- @else
110
- wrax ADDR_PTR, 0.0 ; discard
111
- @endif
112
- ```
113
-
114
- ## 9. Block Macros Recap
115
- - `${input.id}`: Address of input.
116
- - `${output.id}`: Address of output.
117
- - `${mem.id}`: Address of memory.
118
- - `${reg.name}`: Address of register.
119
- - `@section init`: Run once on program startup (e.g., LFO `wlds`). Use `skp run, skip_init`.
120
- - `@section main`: Run every sample.
121
-
122
- ## 10. Memory Writes (`wra` vs `wrax`)
123
- NEVER use `wrax` to write to delay memory!
124
- - **Registers**: Use `wrax` to write into hardware registers (e.g. `wrax ${reg.mix_dry}, 1.0`).
125
- - **Memory**: Use `wra` to write into delay lines (e.g. `wra ${mem.delay_line}, 0.0`).
126
-
127
- ## 11. Dropdown / Combobox Parameters
128
- To create a dropdown option parameter instead of a number slider, use `"type": "select"` and provide an `"options"` array:
129
- ```json
130
- {
131
- "id": "mode",
132
- "name": "Mode",
133
- "type": "select",
134
- "default": 0,
135
- "options": [
136
- { "label": "Gated Reverb", "value": 0 },
137
- { "label": "Reverse Reverb", "value": 1 }
138
- ]
139
- }
140
- ```
141
-
142
- ## 12. Dynamic UI Custom Labels (`labelTemplate`)
143
- If you provide a `"labelTemplate"` in the JSON, you can dynamically display parameter values. You MUST prefix parameter keys with `param.`:
144
- ```json
145
- "labelTemplate": "${param.mode == 0 ? 'Gated Reverb' : 'Reverse Reverb'}"
146
- ```
147
-
148
- ## 13. Exposing POT / CV Connectors
149
- To allow the user to connect external CV inputs (such as FV-1 POTs) to parameters like `Mix` or `Feedback`, you MUST add corresponding entries to the `"inputs"` array of type `"control"`. If it's not in `"inputs"`, the user cannot patch a POT block to it!
150
- ```json
151
- { "id": "mixCV", "name": "Mix", "type": "control", "required": false }
152
- ```
153
-
154
- ## 14. FV-1 `wrap` Instruction Constraints
155
- The `wrap` macro intrinsically dictates `Acc = Acc / 2 + Delay_Read` and `Delay_Write = Acc * 0.5 + Delay_Read`.
156
- Because it implicitly includes the input accumulator in its write back into the delay line, it CANNOT be used in scenarios where the phase of the accumulator needs to be negated or inverted (e.g. `Acc = -Acc / 2 + Delay_Read`). Attempting to negate the accumulator before a `wrap` instruction will cause the delay memory to recursively write back inverted values, forming an unstable positive feedback/resonant filter resulting in metallic ringing artifacts and uncontrollable gain stacking. If explicit mathematical phase tracking is required across all-pass filters without intrinsic gain side-effects, the `wrap` instruction must be manually unrolled using discrete `wra`/`rda`/`wrax`/`rdax` sequences.
1
+ # ATL (Audiofab Template Language) Block Development Reference
2
+
3
+ This document serves as the foundational context and ruleset for creating high-quality FV-1 algorithms as ATL blocks in the FV-1 VS Code Extension.
4
+
5
+ ## 1. File Structure Overview
6
+ Each `.atl` file must consist of two main parts separated by `---`:
7
+ 1. **JSON Configuration Module**: Defines block metadata, inputs, outputs, parameters, memories, and hardware registers.
8
+ 2. **ATL Code Module**: Contains the FV-1 DSP assembly mixed with ATL macros and directives.
9
+
10
+ ## 2. Parameter Conversions
11
+ All parameters should be explicitly mapped using proper conversions. Use the `conversion` key in the parameter JSON.
12
+ - **Gain**: Use `"conversion": "DBLEVEL"` (UI shows dB, code gets linear).
13
+ - **Delay Times**: Use `"conversion": "MS_TO_SAMPLES"` (UI shows ms, code gets sample count).
14
+ - **Frequencies / Rates**: Use `"conversion": "HZ_TO_LFO_RATE"` for LFOs, `"conversion": "LOGFREQ"` for filters.
15
+ - **LFO Width**: Use `"conversion": "MS_TO_LFO_RANGE"`.
16
+
17
+ ## 3. Fallbacks for Control Inputs
18
+ Every control input must have a corresponding "fallback" strategy when the input pin is NOT connected by the user.
19
+
20
+ ### The `@cv` Macro (Recommended)
21
+ The standard way to handle control inputs is using the `@cv` macro. It automatically handles three scenarios based on whether the input port is connected:
22
+ 1. **Unconnected**: Loads the value of the port's associated parameter as a constant (`SOF 0.0, <equ>`).
23
+ 2. **Connected to a standard CV/LFO**: Loads the parameter value and scales it by the pot input (`CLR; SOF 0.0, <equ>; MULX <reg>`), giving ACC ∈ [0..paramValue].
24
+ 3. **Connected to a zero-bypassed Pot**: Uses the 5-instruction bypass block with the pot's `Zero Bypass Value` as the fallback (instead of the parameter). The pot value is scaled by the parameter value via `RDAX reg, <equ>`.
25
+
26
+ The control input JSON **must** include a `"parameter"` field pointing to the parameter that provides the default/range:
27
+
28
+ ```json
29
+ { "id": "mixCV", "name": "Mix", "type": "control", "required": false, "parameter": "mix" }
30
+ ```
31
+
32
+ Usage in the ATL template body — just one line:
33
+
34
+ ```assembly
35
+ ; ACC now holds the correct value (constant or pot-scaled)
36
+ @cv mixCV
37
+ ```
38
+
39
+ ### The `@mulcv` Macro — Scale existing ACC by CV
40
+ Use `@mulcv` when ACC already contains a signal you want to **multiply** by the CV value, without clearing first.
41
+
42
+ | Port state | Generated assembly | Instructions |
43
+ |---|---|---|
44
+ | Unconnected | `SOF paramValue, 0.0` | 1 |
45
+ | Connected | `SOF paramValue, 0.0; MULX reg` | 2 |
46
+ | Zero-bypassed | `WRAX scratch; RDAX reg, equ; bypass; MULX scratch` | 7 |
47
+
48
+ Example — applying a mix CV to a difference signal:
49
+ ```assembly
50
+ rdax ${reg.mix_dry}, -1.0 ; ACC = wet - dry
51
+ @mulcv mixCV ; ACC = (wet - dry) * mix
52
+ rdax ${reg.mix_dry}, 1.0 ; ACC = (wet - dry) * mix + dry
53
+ ```
54
+
55
+ ### Legacy `@if pinConnected` Method
56
+ If you need highly custom logic between bypassed vs active states, you can still manually check if the pin is connected. Note that this method *does not* support the Zero-Bypassed Pot feature natively:
57
+
58
+ ```assembly
59
+ @if pinConnected(mixCV)
60
+ rdax ${input.mixCV}, 1.0
61
+ @else
62
+ sof 0.0, ${mix}
63
+ @endif
64
+ ```
65
+
66
+ ## 4. Input Connection Safeguards
67
+ If the block's main audio input pin is completely disconnected, the block should generally produce no instructions, or handle the bypass effectively, avoiding generating useless cycles.
68
+
69
+ ```assembly
70
+ @section main
71
+ @if pinConnected(input)
72
+ ; ... heavy processing ...
73
+ @else
74
+ ; Block disabled / bypassed
75
+ @endif
76
+ ```
77
+
78
+ ## 5. Memory Management
79
+ Delay block memory allocations MUST be explicitly placed in the `"memories"` JSON array.
80
+ - A fixed size: `{ "id": "pdel", "size": 3276 }`
81
+ - Bound to a parameter (e.g., `delayLength` converted by `MS_TO_SAMPLES`): `{ "id": "delayl", "size": "delayLength" }`
82
+
83
+ In code, reference these with `${mem.pdel}` or `${mem.delayl}`.
84
+ - To access base address: `${mem.id}`
85
+ - To access fractional taps or offset taps: `${mem.id} + offset`
86
+
87
+ ## 6. Registers
88
+ All registers used by the block must be declared in the `"registers"` JSON array.
89
+ Reference them via `${reg.registryName}`. No magic EQU offsets/allocations should be done manually for registers.
90
+ Example: `"registers": ["wet", "dry", "temp"]`
91
+
92
+ ## 7. Magic Numbers & Reusability
93
+ Avoid magic constants scattered throughout the assembly. Declare them using `@equals` in an `@section header`.
94
+ ```assembly
95
+ @section header
96
+ @equals decayLimit 0.8
97
+ @equals bandwidth 0.31852
98
+ ```
99
+ To calculate derived parameters, use `EQU` formulas if needed, e.g.:
100
+ ```assembly
101
+ EQU tap1 (0.9 * ${tap1Center} * ${delayLength})
102
+ ```
103
+
104
+ ## 8. Routing / I/O Defaults
105
+ If left and right outputs exist, verify which are connected to prevent writing to address zero (`ADDR_PTR` trick or just skipping) if the output isn't used:
106
+ ```assembly
107
+ @if pinConnected(outL)
108
+ wrax ${output.outL}, 0.0
109
+ @else
110
+ wrax ADDR_PTR, 0.0 ; discard
111
+ @endif
112
+ ```
113
+
114
+ ## 9. Block Macros Recap
115
+ - `${input.id}`: Address of input.
116
+ - `${output.id}`: Address of output.
117
+ - `${mem.id}`: Address of memory.
118
+ - `${reg.name}`: Address of register.
119
+ - `@section init`: Run once on program startup (e.g., LFO `wlds`). Use `skp run, skip_init`.
120
+ - `@section main`: Run every sample.
121
+
122
+ ## 10. Memory Writes (`wra` vs `wrax`)
123
+ NEVER use `wrax` to write to delay memory!
124
+ - **Registers**: Use `wrax` to write into hardware registers (e.g. `wrax ${reg.mix_dry}, 1.0`).
125
+ - **Memory**: Use `wra` to write into delay lines (e.g. `wra ${mem.delay_line}, 0.0`).
126
+
127
+ ## 11. Dropdown / Combobox Parameters
128
+ To create a dropdown option parameter instead of a number slider, use `"type": "select"` and provide an `"options"` array:
129
+ ```json
130
+ {
131
+ "id": "mode",
132
+ "name": "Mode",
133
+ "type": "select",
134
+ "default": 0,
135
+ "options": [
136
+ { "label": "Gated Reverb", "value": 0 },
137
+ { "label": "Reverse Reverb", "value": 1 }
138
+ ]
139
+ }
140
+ ```
141
+
142
+ ## 12. Dynamic UI Custom Labels (`labelTemplate`)
143
+ If you provide a `"labelTemplate"` in the JSON, you can dynamically display parameter values. You MUST prefix parameter keys with `param.`:
144
+ ```json
145
+ "labelTemplate": "${param.mode == 0 ? 'Gated Reverb' : 'Reverse Reverb'}"
146
+ ```
147
+
148
+ ## 13. Exposing POT / CV Connectors
149
+ To allow the user to connect external CV inputs (such as FV-1 POTs) to parameters like `Mix` or `Feedback`, you MUST add corresponding entries to the `"inputs"` array of type `"control"`. If it's not in `"inputs"`, the user cannot patch a POT block to it!
150
+ ```json
151
+ { "id": "mixCV", "name": "Mix", "type": "control", "required": false }
152
+ ```
153
+
154
+ ## 14. FV-1 `wrap` Instruction Constraints
155
+ The `wrap` macro intrinsically dictates `Acc = Acc / 2 + Delay_Read` and `Delay_Write = Acc * 0.5 + Delay_Read`.
156
+ Because it implicitly includes the input accumulator in its write back into the delay line, it CANNOT be used in scenarios where the phase of the accumulator needs to be negated or inverted (e.g. `Acc = -Acc / 2 + Delay_Read`). Attempting to negate the accumulator before a `wrap` instruction will cause the delay memory to recursively write back inverted values, forming an unstable positive feedback/resonant filter resulting in metallic ringing artifacts and uncontrollable gain stacking. If explicit mathematical phase tracking is required across all-pass filters without intrinsic gain side-effects, the `wrap` instruction must be manually unrolled using discrete `wra`/`rda`/`wrax`/`rdax` sequences.
@@ -1,36 +1,36 @@
1
- ---
2
- {
3
- "type": "control.constant",
4
- "name": "Constant",
5
- "category": "Control",
6
- "description": "Generates a constant control value.",
7
- "color": "#FF9800",
8
- "width": 140,
9
- "labelTemplate": "${param.constant}",
10
- "inputs": [],
11
- "outputs": [
12
- {
13
- "id": "value",
14
- "name": "Value",
15
- "type": "control"
16
- }
17
- ],
18
- "parameters": [
19
- {
20
- "id": "constant",
21
- "name": "Value",
22
- "type": "number",
23
- "default": 0.5,
24
- "min": 0,
25
- "max": 1,
26
- "step": 0.01,
27
- "description": "Constant value (0.0 to 1.0)."
28
- }
29
- ]
30
- }
31
- ---
32
- ; Constant value generator
33
- @section main
34
-
35
- sof 0.0, ${param.constant}
36
- wrax ${output.value}, 0.0
1
+ ---
2
+ {
3
+ "type": "control.constant",
4
+ "name": "Constant",
5
+ "category": "Control",
6
+ "description": "Generates a constant control value.",
7
+ "color": "#FF9800",
8
+ "width": 140,
9
+ "labelTemplate": "${param.constant}",
10
+ "inputs": [],
11
+ "outputs": [
12
+ {
13
+ "id": "value",
14
+ "name": "Value",
15
+ "type": "control"
16
+ }
17
+ ],
18
+ "parameters": [
19
+ {
20
+ "id": "constant",
21
+ "name": "Value",
22
+ "type": "number",
23
+ "default": 0.5,
24
+ "min": 0,
25
+ "max": 1,
26
+ "step": 0.01,
27
+ "description": "Constant value (0.0 to 1.0)."
28
+ }
29
+ ]
30
+ }
31
+ ---
32
+ ; Constant value generator
33
+ @section main
34
+
35
+ sof 0.0, ${param.constant}
36
+ wrax ${output.value}, 0.0
@@ -1,74 +1,74 @@
1
- ---
2
- {
3
- "type": "control.entropy_lfo",
4
- "name": "Entropy LFO",
5
- "category": "Control",
6
- "description": "Chaotic Logistic Map (fixed: subsonic sweep and uppercase label hardening).",
7
- "color": "#f2b824",
8
- "inputs": [
9
- { "id": "speed", "name": "Speed", "type": "control", "required": false, "parameter": "speed" },
10
- { "id": "chaos", "name": "Chaos", "type": "control", "required": false, "parameter": "r_chaos" }
11
- ],
12
- "outputs": [
13
- { "id": "out", "name": "Out", "type": "control" }
14
- ],
15
- "parameters": [
16
- { "id": "speed", "name": "Update Rate", "type": "number", "default": 0.5, "min": 0, "max": 1, "step": 0.01 },
17
- { "id": "r_chaos", "name": "Chaos (r)", "type": "number", "default": 0.98, "min": 0.88, "max": 1.0, "step": 0.01 }
18
- ],
19
- "registers": [ "x", "counter", "temp", "chaos_val", "speed_val" ]
20
- }
21
- ---
22
- @section init
23
- skp run, skip_init_entropy
24
- sof 0.0, 0.432 ; irrational seed
25
- wrax ${reg.x}, 0.0
26
- sof 0.0, 0.0
27
- wrax ${reg.counter}, 0.0
28
- skip_init_entropy:
29
-
30
- @section main
31
- ; 1. Load CV inputs into registers
32
- @cv speed
33
- wrax ${reg.speed_val}, 0.0
34
- @cv chaos
35
- wrax ${reg.chaos_val}, 0.0
36
-
37
- ; 2. Update Counter
38
- rdax ${reg.counter}, 1.0
39
- rdax ${reg.speed_val}, 0.002 ; Max speed ~70Hz (0.95 / 0.00203 / 32768)
40
- sof 1.0, 0.00003 ; Min speed ~1Hz (0.95 / 0.00003 / 32768)
41
- wrax ${reg.counter}, 1.0
42
-
43
- ; 3. Check for Update Event
44
- sof 1.0, -0.95
45
- skp neg, ${local.SKIP_UPDATE}
46
-
47
- ; --- Chaotic Map Block (Runs only on Trigger) ---
48
- clr ; MUST clear ACC after the counter check!
49
- rdax ${reg.x}, 1.0
50
- wrax ${reg.temp}, 1.0 ; temp = x
51
- sof -1.0, 0.999 ; ACC = 1 - x
52
- mulx ${reg.temp} ; ACC = x * (1 - x)
53
- sof 1.999, 0.0 ; Scale (x4)
54
- sof 1.999, 0.0
55
- mulx ${reg.chaos_val} ; Apply chaos factor r
56
- wrax ${reg.x}, 1.0 ; update x
57
-
58
- ; Kickstart: if |x| < 0.01, reset to seed (guards against map stalling at 0)
59
- absa
60
- sof 1.0, -0.01
61
- skp gez, ${local.SKIP_KICK}
62
- sof 0.0, 0.432 ; irrational seed
63
- wrax ${reg.x}, 0.0
64
- ${local.SKIP_KICK}:
65
-
66
- ; Reset counter
67
- sof 0.0, 0.0
68
- wrax ${reg.counter}, 0.0
69
-
70
- ${local.SKIP_UPDATE}:
71
- ; 5. Output (CLEAN)
72
- clr ; Clear ACC before loading output to avoid counter pollution
73
- rdax ${reg.x}, 1.0
74
- wrax ${output.out}, 0.0
1
+ ---
2
+ {
3
+ "type": "control.entropy_lfo",
4
+ "name": "Entropy LFO",
5
+ "category": "Control",
6
+ "description": "Chaotic Logistic Map (fixed: subsonic sweep and uppercase label hardening).",
7
+ "color": "#f2b824",
8
+ "inputs": [
9
+ { "id": "speed", "name": "Speed", "type": "control", "required": false, "parameter": "speed" },
10
+ { "id": "chaos", "name": "Chaos", "type": "control", "required": false, "parameter": "r_chaos" }
11
+ ],
12
+ "outputs": [
13
+ { "id": "out", "name": "Out", "type": "control" }
14
+ ],
15
+ "parameters": [
16
+ { "id": "speed", "name": "Update Rate", "type": "number", "default": 0.5, "min": 0, "max": 1, "step": 0.01 },
17
+ { "id": "r_chaos", "name": "Chaos (r)", "type": "number", "default": 0.98, "min": 0.88, "max": 1.0, "step": 0.01 }
18
+ ],
19
+ "registers": [ "x", "counter", "temp", "chaos_val", "speed_val" ]
20
+ }
21
+ ---
22
+ @section init
23
+ skp run, skip_init_entropy
24
+ sof 0.0, 0.432 ; irrational seed
25
+ wrax ${reg.x}, 0.0
26
+ sof 0.0, 0.0
27
+ wrax ${reg.counter}, 0.0
28
+ skip_init_entropy:
29
+
30
+ @section main
31
+ ; 1. Load CV inputs into registers
32
+ @cv speed
33
+ wrax ${reg.speed_val}, 0.0
34
+ @cv chaos
35
+ wrax ${reg.chaos_val}, 0.0
36
+
37
+ ; 2. Update Counter
38
+ rdax ${reg.counter}, 1.0
39
+ rdax ${reg.speed_val}, 0.002 ; Max speed ~70Hz (0.95 / 0.00203 / 32768)
40
+ sof 1.0, 0.00003 ; Min speed ~1Hz (0.95 / 0.00003 / 32768)
41
+ wrax ${reg.counter}, 1.0
42
+
43
+ ; 3. Check for Update Event
44
+ sof 1.0, -0.95
45
+ skp neg, ${local.SKIP_UPDATE}
46
+
47
+ ; --- Chaotic Map Block (Runs only on Trigger) ---
48
+ clr ; MUST clear ACC after the counter check!
49
+ rdax ${reg.x}, 1.0
50
+ wrax ${reg.temp}, 1.0 ; temp = x
51
+ sof -1.0, 0.999 ; ACC = 1 - x
52
+ mulx ${reg.temp} ; ACC = x * (1 - x)
53
+ sof 1.999, 0.0 ; Scale (x4)
54
+ sof 1.999, 0.0
55
+ mulx ${reg.chaos_val} ; Apply chaos factor r
56
+ wrax ${reg.x}, 1.0 ; update x
57
+
58
+ ; Kickstart: if |x| < 0.01, reset to seed (guards against map stalling at 0)
59
+ absa
60
+ sof 1.0, -0.01
61
+ skp gez, ${local.SKIP_KICK}
62
+ sof 0.0, 0.432 ; irrational seed
63
+ wrax ${reg.x}, 0.0
64
+ ${local.SKIP_KICK}:
65
+
66
+ ; Reset counter
67
+ sof 0.0, 0.0
68
+ wrax ${reg.counter}, 0.0
69
+
70
+ ${local.SKIP_UPDATE}:
71
+ ; 5. Output (CLEAN)
72
+ clr ; Clear ACC before loading output to avoid counter pollution
73
+ rdax ${reg.x}, 1.0
74
+ wrax ${output.out}, 0.0