@audiofab-io/fv1-core 0.2.3 → 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.
- package/blocks/ATL_DEVELOPER_REFERENCE.md +156 -0
- package/blocks/control/constant.atl +36 -0
- package/blocks/control/entropy_lfo.atl +74 -0
- package/blocks/control/envelope.atl +121 -0
- package/blocks/control/invert.atl +33 -0
- package/blocks/control/pot.atl +150 -0
- package/blocks/control/power.atl +77 -0
- package/blocks/control/ramp_lfo.atl +122 -0
- package/blocks/control/scale_offset.atl +84 -0
- package/blocks/control/sincos_lfo.atl +126 -0
- package/blocks/control/smoother.atl +48 -0
- package/blocks/control/tremolizer.atl +55 -0
- package/blocks/effects/delay/micro_stutter.atl +77 -0
- package/blocks/effects/delay/mn3011.atl +281 -0
- package/blocks/effects/delay/simple_delay.atl +96 -0
- package/blocks/effects/delay/triple_tap_delay.atl +176 -0
- package/blocks/effects/lo-fi/bit_mangler.atl +74 -0
- package/blocks/effects/lo-fi/chiptune.atl +311 -0
- package/blocks/effects/lo-fi/tape_degrade.atl +181 -0
- package/blocks/effects/modulation/chorus.atl +141 -0
- package/blocks/effects/modulation/chorus_4voice.atl +188 -0
- package/blocks/effects/modulation/flanger.atl +184 -0
- package/blocks/effects/modulation/guitar_synth.atl +350 -0
- package/blocks/effects/modulation/harmonic_trem.atl +129 -0
- package/blocks/effects/modulation/organ_synth.atl +326 -0
- package/blocks/effects/modulation/phaser.atl +300 -0
- package/blocks/effects/pitch/octave_up_down.atl +80 -0
- package/blocks/effects/pitch/pitch_offset.atl +149 -0
- package/blocks/effects/pitch/pitch_offset_dual.atl +197 -0
- package/blocks/effects/pitch/pitch_shift.atl +115 -0
- package/blocks/effects/pitch/sub_octave.atl +100 -0
- package/blocks/effects/reverb/ducking_reverb.atl +145 -0
- package/blocks/effects/reverb/min_reverb.atl +132 -0
- package/blocks/effects/reverb/plate_reverb.atl +344 -0
- package/blocks/effects/reverb/room_reverb.atl +293 -0
- package/blocks/effects/reverb/smear.atl +90 -0
- package/blocks/effects/reverb/spring_reverb.atl +353 -0
- package/blocks/filter/1p_high_pass.atl +63 -0
- package/blocks/filter/1p_low_pass.atl +59 -0
- package/blocks/filter/auto_wah.atl +207 -0
- package/blocks/filter/bbd_loss.atl +79 -0
- package/blocks/filter/shelving_high_pass.atl +76 -0
- package/blocks/filter/shelving_low_pass.atl +76 -0
- package/blocks/filter/svf_2p.atl +116 -0
- package/blocks/gain_mix/crossfade.atl +93 -0
- package/blocks/gain_mix/crossfade2.atl +86 -0
- package/blocks/gain_mix/crossfade3.atl +71 -0
- package/blocks/gain_mix/gainboost.atl +54 -0
- package/blocks/gain_mix/mixer2.atl +76 -0
- package/blocks/gain_mix/mixer3.atl +109 -0
- package/blocks/gain_mix/mixer4.atl +152 -0
- package/blocks/gain_mix/volume.atl +51 -0
- package/blocks/io/adc.atl +53 -0
- package/blocks/io/dac.atl +61 -0
- package/blocks/other/stickynote.atl +24 -0
- package/blocks/other/tone_gen_adjustable.atl +137 -0
- package/blocks/other/tone_gen_fixed.atl +109 -0
- package/dist/blockDiagram/blocks/BlockDirectoryLoader.d.ts +13 -0
- package/dist/blockDiagram/blocks/BlockDirectoryLoader.d.ts.map +1 -0
- package/dist/blockDiagram/blocks/BlockDirectoryLoader.js +44 -0
- package/dist/blockDiagram/blocks/BlockDirectoryLoader.js.map +1 -0
- package/dist/blockDiagram/blocks/BlockRegistry.d.ts +48 -0
- package/dist/blockDiagram/blocks/BlockRegistry.d.ts.map +1 -0
- package/dist/blockDiagram/blocks/BlockRegistry.js +109 -0
- package/dist/blockDiagram/blocks/BlockRegistry.js.map +1 -0
- package/dist/blockDiagram/blocks/TemplateBlock.d.ts +20 -0
- package/dist/blockDiagram/blocks/TemplateBlock.d.ts.map +1 -0
- package/dist/blockDiagram/blocks/TemplateBlock.js +82 -0
- package/dist/blockDiagram/blocks/TemplateBlock.js.map +1 -0
- package/dist/blockDiagram/blocks/base/BaseBlock.d.ts +248 -0
- package/dist/blockDiagram/blocks/base/BaseBlock.d.ts.map +1 -0
- package/dist/blockDiagram/blocks/base/BaseBlock.js +402 -0
- package/dist/blockDiagram/blocks/base/BaseBlock.js.map +1 -0
- package/dist/blockDiagram/builtinBlocks.d.ts +9 -0
- package/dist/blockDiagram/builtinBlocks.d.ts.map +1 -0
- package/dist/blockDiagram/builtinBlocks.js +4912 -0
- package/dist/blockDiagram/builtinBlocks.js.map +1 -0
- package/dist/blockDiagram/compiler/BlockTemplate.d.ts +37 -0
- package/dist/blockDiagram/compiler/BlockTemplate.d.ts.map +1 -0
- package/dist/blockDiagram/compiler/BlockTemplate.js +860 -0
- package/dist/blockDiagram/compiler/BlockTemplate.js.map +1 -0
- package/dist/blockDiagram/compiler/CodeOptimizer.d.ts +75 -0
- package/dist/blockDiagram/compiler/CodeOptimizer.d.ts.map +1 -0
- package/dist/blockDiagram/compiler/CodeOptimizer.js +443 -0
- package/dist/blockDiagram/compiler/CodeOptimizer.js.map +1 -0
- package/dist/blockDiagram/compiler/GraphCompiler.d.ts +63 -0
- package/dist/blockDiagram/compiler/GraphCompiler.d.ts.map +1 -0
- package/dist/blockDiagram/compiler/GraphCompiler.js +656 -0
- package/dist/blockDiagram/compiler/GraphCompiler.js.map +1 -0
- package/dist/blockDiagram/compiler/TopologicalSort.d.ts +63 -0
- package/dist/blockDiagram/compiler/TopologicalSort.d.ts.map +1 -0
- package/dist/blockDiagram/compiler/TopologicalSort.js +268 -0
- package/dist/blockDiagram/compiler/TopologicalSort.js.map +1 -0
- package/dist/blockDiagram/index.d.ts +30 -0
- package/dist/blockDiagram/index.d.ts.map +1 -0
- package/dist/blockDiagram/index.js +29 -0
- package/dist/blockDiagram/index.js.map +1 -0
- package/dist/blockDiagram/types/Block.d.ts +178 -0
- package/dist/blockDiagram/types/Block.d.ts.map +1 -0
- package/dist/blockDiagram/types/Block.js +5 -0
- package/dist/blockDiagram/types/Block.js.map +1 -0
- package/dist/blockDiagram/types/CodeGenContext.d.ts +235 -0
- package/dist/blockDiagram/types/CodeGenContext.d.ts.map +1 -0
- package/dist/blockDiagram/types/CodeGenContext.js +554 -0
- package/dist/blockDiagram/types/CodeGenContext.js.map +1 -0
- package/dist/blockDiagram/types/Connection.d.ts +17 -0
- package/dist/blockDiagram/types/Connection.d.ts.map +1 -0
- package/dist/blockDiagram/types/Connection.js +5 -0
- package/dist/blockDiagram/types/Connection.js.map +1 -0
- package/dist/blockDiagram/types/Graph.d.ts +28 -0
- package/dist/blockDiagram/types/Graph.d.ts.map +1 -0
- package/dist/blockDiagram/types/Graph.js +24 -0
- package/dist/blockDiagram/types/Graph.js.map +1 -0
- package/dist/blockDiagram/types/IR.d.ts +79 -0
- package/dist/blockDiagram/types/IR.d.ts.map +1 -0
- package/dist/blockDiagram/types/IR.js +6 -0
- package/dist/blockDiagram/types/IR.js.map +1 -0
- package/dist/blockDiagram/utils/SpinCADConverter.d.ts +17 -0
- package/dist/blockDiagram/utils/SpinCADConverter.d.ts.map +1 -0
- package/dist/blockDiagram/utils/SpinCADConverter.js +307 -0
- package/dist/blockDiagram/utils/SpinCADConverter.js.map +1 -0
- package/dist/effect/compileEffect.d.ts +51 -0
- package/dist/effect/compileEffect.d.ts.map +1 -0
- package/dist/effect/compileEffect.js +133 -0
- package/dist/effect/compileEffect.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- 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
|