@audiofab-io/fv1-core 0.2.2 → 0.4.0

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 (133) hide show
  1. package/blocks/ATL_DEVELOPER_REFERENCE.md +156 -0
  2. package/blocks/control/constant.atl +36 -0
  3. package/blocks/control/entropy_lfo.atl +74 -0
  4. package/blocks/control/envelope.atl +121 -0
  5. package/blocks/control/invert.atl +33 -0
  6. package/blocks/control/pot.atl +150 -0
  7. package/blocks/control/power.atl +77 -0
  8. package/blocks/control/ramp_lfo.atl +122 -0
  9. package/blocks/control/scale_offset.atl +84 -0
  10. package/blocks/control/sincos_lfo.atl +126 -0
  11. package/blocks/control/smoother.atl +48 -0
  12. package/blocks/control/tremolizer.atl +55 -0
  13. package/blocks/effects/delay/micro_stutter.atl +77 -0
  14. package/blocks/effects/delay/mn3011.atl +281 -0
  15. package/blocks/effects/delay/simple_delay.atl +96 -0
  16. package/blocks/effects/delay/triple_tap_delay.atl +176 -0
  17. package/blocks/effects/lo-fi/bit_mangler.atl +74 -0
  18. package/blocks/effects/lo-fi/chiptune.atl +311 -0
  19. package/blocks/effects/lo-fi/tape_degrade.atl +181 -0
  20. package/blocks/effects/modulation/chorus.atl +141 -0
  21. package/blocks/effects/modulation/chorus_4voice.atl +188 -0
  22. package/blocks/effects/modulation/flanger.atl +184 -0
  23. package/blocks/effects/modulation/guitar_synth.atl +350 -0
  24. package/blocks/effects/modulation/harmonic_trem.atl +129 -0
  25. package/blocks/effects/modulation/organ_synth.atl +326 -0
  26. package/blocks/effects/modulation/phaser.atl +300 -0
  27. package/blocks/effects/pitch/octave_up_down.atl +80 -0
  28. package/blocks/effects/pitch/pitch_offset.atl +149 -0
  29. package/blocks/effects/pitch/pitch_offset_dual.atl +197 -0
  30. package/blocks/effects/pitch/pitch_shift.atl +115 -0
  31. package/blocks/effects/pitch/sub_octave.atl +100 -0
  32. package/blocks/effects/reverb/ducking_reverb.atl +145 -0
  33. package/blocks/effects/reverb/min_reverb.atl +132 -0
  34. package/blocks/effects/reverb/plate_reverb.atl +344 -0
  35. package/blocks/effects/reverb/room_reverb.atl +293 -0
  36. package/blocks/effects/reverb/smear.atl +90 -0
  37. package/blocks/effects/reverb/spring_reverb.atl +353 -0
  38. package/blocks/filter/1p_high_pass.atl +63 -0
  39. package/blocks/filter/1p_low_pass.atl +59 -0
  40. package/blocks/filter/auto_wah.atl +207 -0
  41. package/blocks/filter/bbd_loss.atl +79 -0
  42. package/blocks/filter/shelving_high_pass.atl +76 -0
  43. package/blocks/filter/shelving_low_pass.atl +76 -0
  44. package/blocks/filter/svf_2p.atl +116 -0
  45. package/blocks/gain_mix/crossfade.atl +93 -0
  46. package/blocks/gain_mix/crossfade2.atl +86 -0
  47. package/blocks/gain_mix/crossfade3.atl +71 -0
  48. package/blocks/gain_mix/gainboost.atl +54 -0
  49. package/blocks/gain_mix/mixer2.atl +76 -0
  50. package/blocks/gain_mix/mixer3.atl +109 -0
  51. package/blocks/gain_mix/mixer4.atl +152 -0
  52. package/blocks/gain_mix/volume.atl +51 -0
  53. package/blocks/io/adc.atl +53 -0
  54. package/blocks/io/dac.atl +61 -0
  55. package/blocks/other/stickynote.atl +24 -0
  56. package/blocks/other/tone_gen_adjustable.atl +137 -0
  57. package/blocks/other/tone_gen_fixed.atl +109 -0
  58. package/dist/blockDiagram/blocks/BlockDirectoryLoader.d.ts +13 -0
  59. package/dist/blockDiagram/blocks/BlockDirectoryLoader.d.ts.map +1 -0
  60. package/dist/blockDiagram/blocks/BlockDirectoryLoader.js +44 -0
  61. package/dist/blockDiagram/blocks/BlockDirectoryLoader.js.map +1 -0
  62. package/dist/blockDiagram/blocks/BlockRegistry.d.ts +48 -0
  63. package/dist/blockDiagram/blocks/BlockRegistry.d.ts.map +1 -0
  64. package/dist/blockDiagram/blocks/BlockRegistry.js +109 -0
  65. package/dist/blockDiagram/blocks/BlockRegistry.js.map +1 -0
  66. package/dist/blockDiagram/blocks/TemplateBlock.d.ts +20 -0
  67. package/dist/blockDiagram/blocks/TemplateBlock.d.ts.map +1 -0
  68. package/dist/blockDiagram/blocks/TemplateBlock.js +82 -0
  69. package/dist/blockDiagram/blocks/TemplateBlock.js.map +1 -0
  70. package/dist/blockDiagram/blocks/base/BaseBlock.d.ts +248 -0
  71. package/dist/blockDiagram/blocks/base/BaseBlock.d.ts.map +1 -0
  72. package/dist/blockDiagram/blocks/base/BaseBlock.js +402 -0
  73. package/dist/blockDiagram/blocks/base/BaseBlock.js.map +1 -0
  74. package/dist/blockDiagram/builtinBlocks.d.ts +9 -0
  75. package/dist/blockDiagram/builtinBlocks.d.ts.map +1 -0
  76. package/dist/blockDiagram/builtinBlocks.js +4912 -0
  77. package/dist/blockDiagram/builtinBlocks.js.map +1 -0
  78. package/dist/blockDiagram/compiler/BlockTemplate.d.ts +37 -0
  79. package/dist/blockDiagram/compiler/BlockTemplate.d.ts.map +1 -0
  80. package/dist/blockDiagram/compiler/BlockTemplate.js +860 -0
  81. package/dist/blockDiagram/compiler/BlockTemplate.js.map +1 -0
  82. package/dist/blockDiagram/compiler/CodeOptimizer.d.ts +75 -0
  83. package/dist/blockDiagram/compiler/CodeOptimizer.d.ts.map +1 -0
  84. package/dist/blockDiagram/compiler/CodeOptimizer.js +443 -0
  85. package/dist/blockDiagram/compiler/CodeOptimizer.js.map +1 -0
  86. package/dist/blockDiagram/compiler/GraphCompiler.d.ts +63 -0
  87. package/dist/blockDiagram/compiler/GraphCompiler.d.ts.map +1 -0
  88. package/dist/blockDiagram/compiler/GraphCompiler.js +656 -0
  89. package/dist/blockDiagram/compiler/GraphCompiler.js.map +1 -0
  90. package/dist/blockDiagram/compiler/TopologicalSort.d.ts +63 -0
  91. package/dist/blockDiagram/compiler/TopologicalSort.d.ts.map +1 -0
  92. package/dist/blockDiagram/compiler/TopologicalSort.js +268 -0
  93. package/dist/blockDiagram/compiler/TopologicalSort.js.map +1 -0
  94. package/dist/blockDiagram/index.d.ts +30 -0
  95. package/dist/blockDiagram/index.d.ts.map +1 -0
  96. package/dist/blockDiagram/index.js +29 -0
  97. package/dist/blockDiagram/index.js.map +1 -0
  98. package/dist/blockDiagram/types/Block.d.ts +178 -0
  99. package/dist/blockDiagram/types/Block.d.ts.map +1 -0
  100. package/dist/blockDiagram/types/Block.js +5 -0
  101. package/dist/blockDiagram/types/Block.js.map +1 -0
  102. package/dist/blockDiagram/types/CodeGenContext.d.ts +235 -0
  103. package/dist/blockDiagram/types/CodeGenContext.d.ts.map +1 -0
  104. package/dist/blockDiagram/types/CodeGenContext.js +554 -0
  105. package/dist/blockDiagram/types/CodeGenContext.js.map +1 -0
  106. package/dist/blockDiagram/types/Connection.d.ts +17 -0
  107. package/dist/blockDiagram/types/Connection.d.ts.map +1 -0
  108. package/dist/blockDiagram/types/Connection.js +5 -0
  109. package/dist/blockDiagram/types/Connection.js.map +1 -0
  110. package/dist/blockDiagram/types/Graph.d.ts +28 -0
  111. package/dist/blockDiagram/types/Graph.d.ts.map +1 -0
  112. package/dist/blockDiagram/types/Graph.js +24 -0
  113. package/dist/blockDiagram/types/Graph.js.map +1 -0
  114. package/dist/blockDiagram/types/IR.d.ts +79 -0
  115. package/dist/blockDiagram/types/IR.d.ts.map +1 -0
  116. package/dist/blockDiagram/types/IR.js +6 -0
  117. package/dist/blockDiagram/types/IR.js.map +1 -0
  118. package/dist/blockDiagram/utils/SpinCADConverter.d.ts +17 -0
  119. package/dist/blockDiagram/utils/SpinCADConverter.d.ts.map +1 -0
  120. package/dist/blockDiagram/utils/SpinCADConverter.js +307 -0
  121. package/dist/blockDiagram/utils/SpinCADConverter.js.map +1 -0
  122. package/dist/effect/compileEffect.d.ts +51 -0
  123. package/dist/effect/compileEffect.d.ts.map +1 -0
  124. package/dist/effect/compileEffect.js +133 -0
  125. package/dist/effect/compileEffect.js.map +1 -0
  126. package/dist/index.d.ts +2 -0
  127. package/dist/index.d.ts.map +1 -1
  128. package/dist/index.js +2 -0
  129. package/dist/index.js.map +1 -1
  130. package/dist/simulator/FV1Simulator.d.ts.map +1 -1
  131. package/dist/simulator/FV1Simulator.js +7 -4
  132. package/dist/simulator/FV1Simulator.js.map +1 -1
  133. package/package.json +17 -5
@@ -0,0 +1,350 @@
1
+ ---
2
+ {
3
+ "type": "effects.modulation.guitar_synth",
4
+ "name": "Guitar Synth",
5
+ "category": "Effects",
6
+ "subcategory": "Modulation",
7
+ "description": "Searing monophonic synth lead. Hard-clips the guitar into a square wave oscillator, pitch-shifts up one octave for brightness, and sweeps a resonant filter on each pick attack. Inspired by the Micro Synthesizer tones of late '70s new wave. Play single notes for the best tracking.",
8
+ "color": "#8833CC",
9
+ "width": 180,
10
+ "inputs": [
11
+ {
12
+ "id": "in",
13
+ "name": "Input",
14
+ "type": "audio",
15
+ "required": true
16
+ },
17
+ {
18
+ "id": "filter_base_cv",
19
+ "name": "Filter Base",
20
+ "type": "control",
21
+ "required": false,
22
+ "parameter": "filter_base"
23
+ },
24
+ {
25
+ "id": "filter_sweep_cv",
26
+ "name": "Filter Sweep",
27
+ "type": "control",
28
+ "required": false,
29
+ "parameter": "filter_sweep"
30
+ },
31
+ {
32
+ "id": "resonance_cv",
33
+ "name": "Resonance",
34
+ "type": "control",
35
+ "required": false,
36
+ "parameter": "resonance"
37
+ },
38
+ {
39
+ "id": "mix_cv",
40
+ "name": "Mix",
41
+ "type": "control",
42
+ "required": false,
43
+ "parameter": "mix"
44
+ }
45
+ ],
46
+ "outputs": [
47
+ {
48
+ "id": "out",
49
+ "name": "Output",
50
+ "type": "audio"
51
+ }
52
+ ],
53
+ "parameters": [
54
+ {
55
+ "id": "drive",
56
+ "name": "Oscillator Drive",
57
+ "type": "number",
58
+ "default": 1.5,
59
+ "min": 0.5,
60
+ "max": 1.99,
61
+ "step": 0.01,
62
+ "description": "Pre-gain into the hard clipper. Higher values sustain the square wave longer as the guitar decays."
63
+ },
64
+ {
65
+ "id": "octave_level",
66
+ "name": "Octave Up",
67
+ "type": "number",
68
+ "default": 0.7,
69
+ "min": 0.0,
70
+ "max": 1.5,
71
+ "step": 0.05,
72
+ "description": "Level of the +1 octave voice. This is what makes the lead cut — the synth sits above the guitar."
73
+ },
74
+ {
75
+ "id": "fundamental",
76
+ "name": "Fundamental",
77
+ "type": "number",
78
+ "default": 0.5,
79
+ "min": 0.0,
80
+ "max": 1.5,
81
+ "step": 0.05,
82
+ "description": "Level of the fundamental square wave voice."
83
+ },
84
+ {
85
+ "id": "filter_base",
86
+ "name": "Filter Base",
87
+ "type": "number",
88
+ "default": 1500,
89
+ "min": 300,
90
+ "max": 5000,
91
+ "step": 10,
92
+ "conversion": "SVFFREQ",
93
+ "description": "Resting filter frequency. High values keep the tone bright and searing even between picks."
94
+ },
95
+ {
96
+ "id": "filter_sweep",
97
+ "name": "Filter Sweep",
98
+ "type": "number",
99
+ "default": 0.35,
100
+ "min": 0.0,
101
+ "max": 0.6,
102
+ "step": 0.01,
103
+ "description": "How far the envelope sweeps the filter on each pick. Adds the 'pew' synth attack."
104
+ },
105
+ {
106
+ "id": "resonance",
107
+ "name": "Resonance",
108
+ "type": "number",
109
+ "default": 0.85,
110
+ "min": 0.0,
111
+ "max": 0.97,
112
+ "step": 0.01,
113
+ "description": "Filter Q. High values give the focused, laser-like synth lead character."
114
+ },
115
+ {
116
+ "id": "attack",
117
+ "name": "Attack",
118
+ "type": "number",
119
+ "default": 0.15,
120
+ "min": 0.01,
121
+ "max": 0.5,
122
+ "step": 0.01,
123
+ "description": "Envelope attack speed. Fast attack tracks every pick for snappy synth response."
124
+ },
125
+ {
126
+ "id": "release",
127
+ "name": "Release",
128
+ "type": "number",
129
+ "default": 0.003,
130
+ "min": 0.001,
131
+ "max": 0.02,
132
+ "step": 0.001,
133
+ "description": "Envelope release speed. Controls how quickly the filter closes after a pick."
134
+ },
135
+ {
136
+ "id": "vibrato_rate",
137
+ "name": "Vibrato Rate (Hz)",
138
+ "type": "number",
139
+ "default": 5.5,
140
+ "min": 0.0,
141
+ "max": 10.0,
142
+ "step": 0.1,
143
+ "conversion": "HZ_TO_LFO_RATE",
144
+ "description": "Vibrato speed. Classic synth lead vibrato sits around 5-6 Hz."
145
+ },
146
+ {
147
+ "id": "vibrato_depth",
148
+ "name": "Vibrato Depth (ms)",
149
+ "type": "number",
150
+ "default": 0.5,
151
+ "min": 0.0,
152
+ "max": 3.0,
153
+ "step": 0.1,
154
+ "conversion": "MS_TO_LFO_RANGE",
155
+ "description": "Vibrato depth. Subtle values add life without detuning. Set to 0 for no vibrato."
156
+ },
157
+ {
158
+ "id": "mix",
159
+ "name": "Dry/Wet Mix",
160
+ "type": "number",
161
+ "default": 1.0,
162
+ "min": 0.0,
163
+ "max": 1.0,
164
+ "step": 0.01
165
+ }
166
+ ],
167
+ "memories": [
168
+ {
169
+ "id": "oct_buf",
170
+ "size": 4096
171
+ },
172
+ {
173
+ "id": "oct_temp",
174
+ "size": 1
175
+ },
176
+ {
177
+ "id": "vib_buf",
178
+ "size": 512
179
+ }
180
+ ],
181
+ "registers": [
182
+ "env",
183
+ "hp_state",
184
+ "oscillator",
185
+ "oct_voice",
186
+ "voice_mix",
187
+ "bp",
188
+ "lp",
189
+ "freq_reg",
190
+ "damp_reg",
191
+ "sweep_reg",
192
+ "base_reg",
193
+ "dry",
194
+ "mix_reg"
195
+ ]
196
+ }
197
+ ---
198
+ @section header
199
+ @equals vib_center ${mem.vib_buf} + 256
200
+
201
+ @section init
202
+ skp run, done_init
203
+ ; RMP0: octave up (+1 oct = rate 16384)
204
+ wldr RMP0, 16384, 4096
205
+ ; SIN0: vibrato
206
+ wlds SIN0, ${param.vibrato_rate}, ${param.vibrato_depth}
207
+ done_init:
208
+
209
+ @section main
210
+ @if pinConnected(in)
211
+
212
+ ; ======================================================
213
+ ; Stage 0: Save dry signal
214
+ ; ======================================================
215
+ rdax ${input.in}, 1.0
216
+ wrax ${reg.dry}, 0.0
217
+
218
+ ; ======================================================
219
+ ; Stage 1: Envelope Follower (fast attack, moderate release)
220
+ ; Tracks every pick for snappy synth filter response.
221
+ ; ======================================================
222
+ rdax ${input.in}, 1.0
223
+ sof 1.99, 0.0 ; 2x pre-boost for detection
224
+ absa
225
+ rdax ${reg.env}, -1.0 ; ACC = |input| - env
226
+ skp gez, ${local.ATK}
227
+ ; Release path
228
+ sof ${param.release}, 0.0
229
+ skp run, ${local.UPD}
230
+ ${local.ATK}:
231
+ sof ${param.attack}, 0.0
232
+ ${local.UPD}:
233
+ rdax ${reg.env}, 1.0
234
+ wrax ${reg.env}, 0.0
235
+
236
+ ; ======================================================
237
+ ; Stage 2: VCO — Hard-clip guitar into square wave
238
+ ;
239
+ ; Highpass removes low-freq content for cleaner clipping,
240
+ ; then pre-gain + triple saturation produces a constant-
241
+ ; amplitude square wave rich in odd harmonics.
242
+ ; ======================================================
243
+
244
+ ; Highpass (~200 Hz) for clean clipping
245
+ rdax ${input.in}, 1.0
246
+ rdax ${reg.hp_state}, -1.0
247
+ sof 0.04, 0.0
248
+ rdax ${reg.hp_state}, 1.0
249
+ wrax ${reg.hp_state}, -1.0
250
+ rdax ${input.in}, 1.0 ; ACC = input - LP = highpassed
251
+
252
+ ; Pre-gain + hard clip
253
+ sof ${param.drive}, 0.0
254
+ sof 1.99, 0.0
255
+ sof 1.99, 0.0
256
+ sof 1.99, 0.0
257
+ sof 0.25, 0.0
258
+ wrax ${reg.oscillator}, 0.0
259
+
260
+ ; ======================================================
261
+ ; Stage 3: Octave Up (+1 oct via RMP0)
262
+ ; The octave up is what makes it a LEAD — sits above the
263
+ ; guitar, cuts through the mix.
264
+ ; ======================================================
265
+ rdax ${reg.oscillator}, 1.0
266
+ wra ${mem.oct_buf}, 0.0
267
+
268
+ cho rda, RMP0, REG | COMPC, ${mem.oct_buf}
269
+ cho rda, RMP0, 0, ${mem.oct_buf} + 1
270
+ wra ${mem.oct_temp}, 0.0
271
+ cho rda, RMP0, RPTR2 | COMPC, ${mem.oct_buf}
272
+ cho rda, RMP0, RPTR2, ${mem.oct_buf} + 1
273
+ cho sof, RMP0, NA | COMPC, 0.0
274
+ cho rda, RMP0, NA, ${mem.oct_temp}
275
+
276
+ ; Scale octave up level
277
+ sof ${param.octave_level}, 0.0
278
+ wrax ${reg.oct_voice}, 0.0
279
+
280
+ ; ======================================================
281
+ ; Stage 4: Voice Mixer + Vibrato
282
+ ; ======================================================
283
+ ; Mix fundamental + octave up
284
+ rdax ${reg.oscillator}, ${param.fundamental}
285
+ rdax ${reg.oct_voice}, 1.0
286
+
287
+ ; Write to vibrato delay
288
+ wra ${mem.vib_buf}, 0.0
289
+
290
+ ; Read with vibrato LFO
291
+ cho rda, SIN0, SIN | REG | COMPC, ${vib_center}
292
+ cho rda, SIN0, SIN, ${vib_center} + 1
293
+
294
+ ; ======================================================
295
+ ; Stage 5: Prepare filter coefficients
296
+ ; ======================================================
297
+ wrax ${reg.voice_mix}, 0.0 ; Save vibrato output
298
+
299
+ ; Damping: damp = 1 - resonance
300
+ @cv resonance_cv
301
+ sof -1.0, 1.0
302
+ wrax ${reg.damp_reg}, 0.0
303
+
304
+ ; Swept cutoff: freq = base + env * sweep
305
+ @cv filter_sweep_cv
306
+ wrax ${reg.sweep_reg}, 0.0
307
+
308
+ @cv filter_base_cv
309
+ wrax ${reg.base_reg}, 0.0
310
+
311
+ rdax ${reg.env}, 1.0
312
+ mulx ${reg.sweep_reg}
313
+ rdax ${reg.base_reg}, 1.0
314
+ wrax ${reg.freq_reg}, 0.0
315
+
316
+ ; ======================================================
317
+ ; Stage 6: Resonant SVF (Lowpass)
318
+ ; The resonant peak + bright base frequency gives the
319
+ ; searing, focused synth lead character.
320
+ ; ======================================================
321
+ rdax ${reg.voice_mix}, 1.0 ; Reload vibrato output
322
+ rdax ${reg.lp}, -1.0
323
+ wrax ${reg.voice_mix}, 0.0 ; temp = (input - lp_old)
324
+
325
+ rdax ${reg.bp}, 1.0
326
+ mulx ${reg.damp_reg}
327
+ rdax ${reg.voice_mix}, -1.0 ; ACC = damp*bp - (input - lp)
328
+ sof -1.0, 0.0 ; ACC = HP
329
+
330
+ mulx ${reg.freq_reg} ; ACC = F * HP
331
+ rdax ${reg.bp}, 1.0
332
+ wrax ${reg.bp}, 1.0 ; bp_new
333
+
334
+ mulx ${reg.freq_reg} ; ACC = F * bp_new
335
+ rdax ${reg.lp}, 1.0
336
+ wrax ${reg.lp}, 0.0 ; lp_new
337
+
338
+ ; ======================================================
339
+ ; Stage 7: Dry/Wet Mix
340
+ ; ======================================================
341
+ @cv mix_cv
342
+ wrax ${reg.mix_reg}, 0.0
343
+
344
+ rdax ${reg.lp}, 1.0
345
+ rdax ${reg.dry}, -1.0
346
+ mulx ${reg.mix_reg}
347
+ rdax ${reg.dry}, 1.0
348
+ wrax ${output.out}, 0.0
349
+
350
+ @endif
@@ -0,0 +1,129 @@
1
+ ---
2
+ {
3
+ "type": "fx.harmonic_tremolo",
4
+ "name": "Harmonic Tremolo",
5
+ "category": "Effects",
6
+ "subcategory": "Modulation",
7
+ "description": "True vintage harmonic tremolo using a crossover.",
8
+ "color": "#24F2F2",
9
+ "width": 180,
10
+ "inputs": [
11
+ {
12
+ "id": "in",
13
+ "name": "Input",
14
+ "type": "audio",
15
+ "required": true
16
+ },
17
+ {
18
+ "id": "rate_cv",
19
+ "name": "Rate",
20
+ "type": "control",
21
+ "required": false,
22
+ "parameter": "rate"
23
+ },
24
+ {
25
+ "id": "depth_cv",
26
+ "name": "Depth",
27
+ "type": "control",
28
+ "required": false,
29
+ "parameter": "depth"
30
+ }
31
+ ],
32
+ "outputs": [
33
+ {
34
+ "id": "out",
35
+ "name": "Output",
36
+ "type": "audio"
37
+ }
38
+ ],
39
+ "parameters": [
40
+ {
41
+ "id": "rate",
42
+ "name": "Tremolo Rate (Hz)",
43
+ "type": "number",
44
+ "default": 3.0,
45
+ "min": 0.5,
46
+ "max": 12.0,
47
+ "step": 0.1,
48
+ "conversion": "HZ_TO_LFO_RATE"
49
+ },
50
+ {
51
+ "id": "depth",
52
+ "name": "Depth",
53
+ "type": "number",
54
+ "default": 1.0,
55
+ "min": 0.0,
56
+ "max": 1.0,
57
+ "step": 0.01,
58
+ "description": "Intensity of the tremolo effect."
59
+ },
60
+ {
61
+ "id": "crossover",
62
+ "name": "Crossover Freq",
63
+ "type": "number",
64
+ "default": 600,
65
+ "min": 100,
66
+ "max": 2000,
67
+ "step": 10,
68
+ "conversion": "SVFFREQ",
69
+ "description": "Frequency split for the two bands."
70
+ }
71
+ ],
72
+ "registers": [
73
+ "lpf_state",
74
+ "lfo_val",
75
+ "lfo_inv",
76
+ "depth_temp"
77
+ ]
78
+ }
79
+ ---
80
+ @section init
81
+ skp run, init_trem
82
+ ; Depth in WLDS is useless for RDAL (RDAL reads raw sine), so max it
83
+ wlds SIN0, ${rate}, 32767
84
+ init_trem:
85
+
86
+ @section main
87
+ ; 0. Evaluate Rate CV dynamically (Scaled manually to avoid SOF > 1.99 limits from HZ_TO_LFO_RATE bounds)
88
+ @if pinConnected(rate_cv)
89
+ rdax ${input.rate_cv}, ${rate} / 511.0
90
+ wrax SIN0_RATE, 0.0
91
+ @endif
92
+
93
+ ; 1. Evaluate Depth CV dynamically
94
+ @cv depth_cv ; ACC = Depth (0.0 to 1.0)
95
+ sof 0.5, 0.0 ; ACC = Depth / 2
96
+ wrax ${reg.depth_temp}, 0.0 ; Save scaled depth
97
+
98
+ ; 2. Generate LFO
99
+ cho rdal, SIN0 ; ACC = LFO (-1.0 to 1.0)
100
+ mulx ${reg.depth_temp} ; ACC = LFO * (Depth / 2)
101
+ sof 1.0, 0.5 ; ACC = LFO * (Depth / 2) + 0.5 (Scale to 0.0 - 1.0)
102
+ wrax ${reg.lfo_val}, -1.0 ; Save LFO_VAL, ACC = -LFO_VAL
103
+ sof 1.0, 1.0 ; ACC = 1.0 - LFO_VAL
104
+ wrax ${reg.lfo_inv}, 0.0 ; Save LFO_INV, ACC = 0
105
+
106
+ ; 2. Crossover Filter (1-Pole)
107
+ ; Lowpass = L_old + F * (Input - L_old)
108
+ rdax ${input.in}, 1.0 ; ACC = Input
109
+ rdax ${reg.lpf_state}, -1.0 ; ACC = Input - L_old
110
+ sof ${param.crossover}, 0.0 ; ACC = F * (Input - L_old)
111
+ rdax ${reg.lpf_state}, 1.0 ; ACC = F * (Input - L_old) + L_old
112
+ wrax ${reg.lpf_state}, -1.0 ; REG_L = Lowpass, ACC = -Lowpass
113
+
114
+ ; Highpass = Input - Lowpass
115
+ rdax ${input.in}, 1.0 ; ACC = Input - Lowpass = Highpass
116
+
117
+ ; 3. Modulate Highpass
118
+ mulx ${reg.lfo_inv} ; ACC = Highpass * LFO_INV
119
+
120
+ ; 4. Modulate Lowpass & Mix
121
+ ; Need to bring Highpass to a free register, but we can just use lfo_inv as a temp
122
+ wrax ${reg.lfo_inv}, 0.0 ; Save modulated Highpass in lfo_inv
123
+
124
+ rdax ${reg.lpf_state}, 1.0 ; ACC = Lowpass
125
+ mulx ${reg.lfo_val} ; ACC = Lowpass * LFO_VAL
126
+ rdax ${reg.lfo_inv}, 1.0 ; ACC = (Lowpass * LFO) + (Highpass * LFO_INV)
127
+
128
+ ; 5. Output
129
+ wrax ${output.out}, 0.0