@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,109 @@
1
+ ---
2
+ {
3
+ "type": "other.tonegen.fixed",
4
+ "category": "Other",
5
+ "name": "Tone Generator (Fixed)",
6
+ "description": "Fixed frequency sine wave generator with amplitude control",
7
+ "color": "#FF9800",
8
+ "labelTemplate": "${param.frequency} Hz",
9
+ "inputs": [
10
+ { "id": "amplitude", "name": "Amplitude", "type": "control", "required": false }
11
+ ],
12
+ "outputs": [
13
+ { "id": "out", "name": "Output", "type": "audio" }
14
+ ],
15
+ "parameters": [
16
+ {
17
+ "id": "frequency",
18
+ "name": "Frequency",
19
+ "type": "number",
20
+ "default": 440,
21
+ "min": 20,
22
+ "max": 10000,
23
+ "step": 1
24
+ },
25
+ {
26
+ "id": "amplitude",
27
+ "name": "Amplitude",
28
+ "type": "number",
29
+ "default": 0.5,
30
+ "min": 0.0,
31
+ "max": 1.0,
32
+ "step": 0.01
33
+ }
34
+ ],
35
+ "registers": [
36
+ "freq", "s", "c", "p2fil", "amp"
37
+ ]
38
+ }
39
+ ---
40
+ @section init
41
+ ; Tone Generator (Fixed) init
42
+ skp run, tonegen_fixed_init
43
+ sof 0.0, 0.5
44
+ wrax ${reg.s}, 0.0
45
+ ; The angle for frequency is approx (2*PI*freq) / (SampleRate*4)
46
+ sof 0.0, (6.2831853 * ${frequency}) / 131072.0
47
+ wrax ${reg.freq}, 0.0
48
+ tonegen_fixed_init:
49
+
50
+ @section main
51
+ ; Sine Wave Generator - ${frequency} Hz (fixed)
52
+
53
+ ; Calculate amplitude (dB/step)
54
+ @if pinConnected(amplitude)
55
+ rdax ${input.amplitude}, 0.9375
56
+ @else
57
+ sof 0.0, (${amplitude} * 0.9375)
58
+ @endif
59
+
60
+ ; Filter amplitude control
61
+ rdfx ${reg.p2fil}, 0.01
62
+ wrax ${reg.p2fil}, 1.0
63
+ sof 1.0, -0.9375
64
+ exp 1.0, 0.0
65
+ wrax ${reg.amp}, 0.0
66
+
67
+ ; Rotation matrix oscillator (4x oversampled)
68
+
69
+ ; Iteration 1
70
+ rdax ${reg.c}, 1.0
71
+ mulx ${reg.freq}
72
+ rdax ${reg.s}, 1.0
73
+ wrax ${reg.s}, -1.0
74
+ mulx ${reg.freq}
75
+ rdax ${reg.c}, 1.0
76
+ wrax ${reg.c}, 0.0
77
+
78
+ ; Iteration 2
79
+ rdax ${reg.c}, 1.0
80
+ mulx ${reg.freq}
81
+ rdax ${reg.s}, 1.0
82
+ wrax ${reg.s}, -1.0
83
+ mulx ${reg.freq}
84
+ rdax ${reg.c}, 1.0
85
+ wrax ${reg.c}, 0.0
86
+
87
+ ; Iteration 3
88
+ rdax ${reg.c}, 1.0
89
+ mulx ${reg.freq}
90
+ rdax ${reg.s}, 1.0
91
+ wrax ${reg.s}, -1.0
92
+ mulx ${reg.freq}
93
+ rdax ${reg.c}, 1.0
94
+ wrax ${reg.c}, 0.0
95
+
96
+ ; Iteration 4 (final - accumulate in ACC)
97
+ rdax ${reg.c}, 1.0
98
+ mulx ${reg.freq}
99
+ rdax ${reg.s}, 1.0
100
+ wrax ${reg.s}, -1.0
101
+ mulx ${reg.freq}
102
+ rdax ${reg.c}, 1.0
103
+ wrax ${reg.c}, 1.99
104
+
105
+ ; Scale output by amplitude
106
+ mulx ${reg.amp}
107
+
108
+ ; Write to output
109
+ wrax ${output.out}, 0.0
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Node-only: recursively load ATL / JSON block definitions from a directory
3
+ * into a BlockRegistry. Kept separate from BlockRegistry so browser consumers
4
+ * never pull in `fs` / `path`.
5
+ */
6
+ import { BlockRegistry } from './BlockRegistry.js';
7
+ /**
8
+ * Recursively load .atl and .json block definitions from a directory into
9
+ * the provided registry. Errors on individual files are logged and skipped
10
+ * so one malformed file doesn't break the whole load.
11
+ */
12
+ export declare function loadBlocksFromDirectory(registry: BlockRegistry, dir: string): void;
13
+ //# sourceMappingURL=BlockDirectoryLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockDirectoryLoader.d.ts","sourceRoot":"","sources":["../../../src/blockDiagram/blocks/BlockDirectoryLoader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CA2BlF"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Node-only: recursively load ATL / JSON block definitions from a directory
3
+ * into a BlockRegistry. Kept separate from BlockRegistry so browser consumers
4
+ * never pull in `fs` / `path`.
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import { BlockRegistry } from './BlockRegistry.js';
9
+ /**
10
+ * Recursively load .atl and .json block definitions from a directory into
11
+ * the provided registry. Errors on individual files are logged and skipped
12
+ * so one malformed file doesn't break the whole load.
13
+ */
14
+ export function loadBlocksFromDirectory(registry, dir) {
15
+ if (!fs.existsSync(dir)) {
16
+ return;
17
+ }
18
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
19
+ for (const entry of entries) {
20
+ const fullPath = path.join(dir, entry.name);
21
+ if (entry.isDirectory()) {
22
+ loadBlocksFromDirectory(registry, fullPath);
23
+ continue;
24
+ }
25
+ if (!entry.isFile())
26
+ continue;
27
+ try {
28
+ if (entry.name.endsWith('.json')) {
29
+ const content = fs.readFileSync(fullPath, 'utf8');
30
+ const definition = JSON.parse(content);
31
+ registry.registerDefinition(definition);
32
+ }
33
+ else if (entry.name.endsWith('.atl')) {
34
+ const content = fs.readFileSync(fullPath, 'utf8');
35
+ const definition = BlockRegistry.parseAtl(content);
36
+ registry.registerDefinition(definition);
37
+ }
38
+ }
39
+ catch (e) {
40
+ console.error(`Failed to load block definition ${fullPath}: ${e}`);
41
+ }
42
+ }
43
+ }
44
+ //# sourceMappingURL=BlockDirectoryLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockDirectoryLoader.js","sourceRoot":"","sources":["../../../src/blockDiagram/blocks/BlockDirectoryLoader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAuB,EAAE,GAAW;IACxE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO;IACX,CAAC;IACD,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACtB,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC5C,SAAS;QACb,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,SAAS;QAE9B,IAAI,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAClD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;gBAClE,QAAQ,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;YAC5C,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAClD,MAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBACnD,QAAQ,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;YAC5C,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,mCAAmC,QAAQ,KAAK,CAAC,EAAE,CAAC,CAAC;QACvE,CAAC;IACL,CAAC;AACL,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Central registry for all available block types.
3
+ *
4
+ * Pure in-memory registry with no filesystem dependencies — runs in both
5
+ * Node (VS Code extension) and the browser. Consumers populate it via
6
+ * `loadManifest(defs)` or `register(block)`. For node-based directory
7
+ * scanning, see `./BlockDirectoryLoader.ts`.
8
+ */
9
+ import { IBlockDefinition, BlockMetadata } from '../types/Block.js';
10
+ import { BlockTemplateDefinition } from '../types/IR.js';
11
+ export declare class BlockRegistry {
12
+ private blocks;
13
+ private categories;
14
+ private _onDidChangeBlocks;
15
+ readonly onDidChangeBlocks: (listener: (e: void) => void) => {
16
+ dispose: () => void;
17
+ };
18
+ /** Register a single already-instantiated block definition. */
19
+ register(block: IBlockDefinition): void;
20
+ /** Register a template definition (convenience around TemplateBlock). */
21
+ registerDefinition(definition: BlockTemplateDefinition): void;
22
+ /** Register a batch of template definitions (e.g. the built-in manifest). */
23
+ loadManifest(definitions: BlockTemplateDefinition[]): void;
24
+ /** Clear all registered blocks (used by refresh flows). */
25
+ clear(): void;
26
+ /** Notify subscribers that the registry contents have changed. */
27
+ fireChanged(): void;
28
+ /**
29
+ * Parse an ATL file body into a template definition. Format:
30
+ * ---
31
+ * { JSON metadata }
32
+ * ---
33
+ * assembly template body
34
+ */
35
+ static parseAtl(content: string): BlockTemplateDefinition;
36
+ getBlock(type: string): IBlockDefinition | undefined;
37
+ getAllTypes(): string[];
38
+ getBlocksByCategory(category: string): IBlockDefinition[];
39
+ getCategories(): string[];
40
+ getAllMetadata(): BlockMetadata[];
41
+ getMetadataByCategory(): Map<string, BlockMetadata[]>;
42
+ }
43
+ /**
44
+ * Default singleton — convenient for single-registry applications
45
+ * (the VS Code extension). Create your own instance for isolation if needed.
46
+ */
47
+ export declare const blockRegistry: BlockRegistry;
48
+ //# sourceMappingURL=BlockRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockRegistry.d.ts","sourceRoot":"","sources":["../../../src/blockDiagram/blocks/BlockRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAczD,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAoC;IAEtD,OAAO,CAAC,kBAAkB,CAA4B;IACtD,SAAgB,iBAAiB,0BAdG,IAAI;;MAc0B;IAElE,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAQvC,yEAAyE;IACzE,kBAAkB,CAAC,UAAU,EAAE,uBAAuB,GAAG,IAAI;IAI7D,6EAA6E;IAC7E,YAAY,CAAC,WAAW,EAAE,uBAAuB,EAAE,GAAG,IAAI;IAM1D,2DAA2D;IAC3D,KAAK,IAAI,IAAI;IAKb,kEAAkE;IAClE,WAAW,IAAI,IAAI;IAInB;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,uBAAuB;IAczD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAIpD,WAAW,IAAI,MAAM,EAAE;IAIvB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE;IAKzD,aAAa,IAAI,MAAM,EAAE;IAIzB,cAAc,IAAI,aAAa,EAAE;IAIjC,qBAAqB,IAAI,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC;CAUxD;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,eAAsB,CAAC"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Central registry for all available block types.
3
+ *
4
+ * Pure in-memory registry with no filesystem dependencies — runs in both
5
+ * Node (VS Code extension) and the browser. Consumers populate it via
6
+ * `loadManifest(defs)` or `register(block)`. For node-based directory
7
+ * scanning, see `./BlockDirectoryLoader.ts`.
8
+ */
9
+ import { TemplateBlock } from './TemplateBlock.js';
10
+ // Minimal event emitter so the registry stays free of any host API.
11
+ class EventEmitter {
12
+ constructor() {
13
+ this.listeners = [];
14
+ this.event = (listener) => {
15
+ this.listeners.push(listener);
16
+ return { dispose: () => { this.listeners = this.listeners.filter(l => l !== listener); } };
17
+ };
18
+ }
19
+ fire(data) {
20
+ this.listeners.forEach(l => l(data));
21
+ }
22
+ }
23
+ export class BlockRegistry {
24
+ constructor() {
25
+ this.blocks = new Map();
26
+ this.categories = new Map();
27
+ this._onDidChangeBlocks = new EventEmitter();
28
+ this.onDidChangeBlocks = this._onDidChangeBlocks.event;
29
+ }
30
+ /** Register a single already-instantiated block definition. */
31
+ register(block) {
32
+ this.blocks.set(block.type, block);
33
+ if (!this.categories.has(block.category)) {
34
+ this.categories.set(block.category, []);
35
+ }
36
+ this.categories.get(block.category).push(block.type);
37
+ }
38
+ /** Register a template definition (convenience around TemplateBlock). */
39
+ registerDefinition(definition) {
40
+ this.register(new TemplateBlock(definition));
41
+ }
42
+ /** Register a batch of template definitions (e.g. the built-in manifest). */
43
+ loadManifest(definitions) {
44
+ for (const def of definitions) {
45
+ this.registerDefinition(def);
46
+ }
47
+ }
48
+ /** Clear all registered blocks (used by refresh flows). */
49
+ clear() {
50
+ this.blocks.clear();
51
+ this.categories.clear();
52
+ }
53
+ /** Notify subscribers that the registry contents have changed. */
54
+ fireChanged() {
55
+ this._onDidChangeBlocks.fire();
56
+ }
57
+ /**
58
+ * Parse an ATL file body into a template definition. Format:
59
+ * ---
60
+ * { JSON metadata }
61
+ * ---
62
+ * assembly template body
63
+ */
64
+ static parseAtl(content) {
65
+ const parts = content.split('---');
66
+ if (parts.length < 3) {
67
+ throw new Error('Invalid ATL format: missing frontmatter delimiters (---)');
68
+ }
69
+ const metadata = JSON.parse(parts[1].trim());
70
+ const template = parts.slice(2).join('---').trim();
71
+ return {
72
+ ...metadata,
73
+ template,
74
+ _rawAtl: content,
75
+ };
76
+ }
77
+ getBlock(type) {
78
+ return this.blocks.get(type);
79
+ }
80
+ getAllTypes() {
81
+ return Array.from(this.blocks.keys());
82
+ }
83
+ getBlocksByCategory(category) {
84
+ const types = this.categories.get(category) || [];
85
+ return types.map(type => this.blocks.get(type)).filter(b => b !== undefined);
86
+ }
87
+ getCategories() {
88
+ return Array.from(this.categories.keys());
89
+ }
90
+ getAllMetadata() {
91
+ return Array.from(this.blocks.values()).map(block => block.getMetadata());
92
+ }
93
+ getMetadataByCategory() {
94
+ const result = new Map();
95
+ for (const [category, types] of this.categories.entries()) {
96
+ const metadata = types
97
+ .map(type => this.blocks.get(type)?.getMetadata())
98
+ .filter(m => m !== undefined);
99
+ result.set(category, metadata);
100
+ }
101
+ return result;
102
+ }
103
+ }
104
+ /**
105
+ * Default singleton — convenient for single-registry applications
106
+ * (the VS Code extension). Create your own instance for isolation if needed.
107
+ */
108
+ export const blockRegistry = new BlockRegistry();
109
+ //# sourceMappingURL=BlockRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockRegistry.js","sourceRoot":"","sources":["../../../src/blockDiagram/blocks/BlockRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * TemplateBlock
3
+ * Wrapper for declarative block definitions using the BlockTemplate engine.
4
+ */
5
+ import { BaseBlock } from './base/BaseBlock.js';
6
+ import { BlockTemplateDefinition } from '../types/IR.js';
7
+ import { CodeGenContext } from '../types/Block.js';
8
+ export declare class TemplateBlock extends BaseBlock {
9
+ readonly type: string;
10
+ readonly category: string;
11
+ readonly subcategory?: string;
12
+ readonly name: string;
13
+ readonly description: string;
14
+ private templateEngine;
15
+ constructor(definition: BlockTemplateDefinition);
16
+ getCustomLabel(params: Record<string, any>, ctx?: any, blockId?: string): string | null;
17
+ generateCode(ctx: CodeGenContext): void;
18
+ getRawTemplate(): string | undefined;
19
+ }
20
+ //# sourceMappingURL=TemplateBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemplateBlock.d.ts","sourceRoot":"","sources":["../../../src/blockDiagram/blocks/TemplateBlock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,qBAAa,aAAc,SAAQ,SAAS;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,SAAiB,WAAW,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,OAAO,CAAC,cAAc,CAAgB;gBAE1B,UAAU,EAAE,uBAAuB;IAsC/C,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAiBvF,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAQvC,cAAc,IAAI,MAAM,GAAG,SAAS;CAevC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * TemplateBlock
3
+ * Wrapper for declarative block definitions using the BlockTemplate engine.
4
+ */
5
+ import { BaseBlock } from './base/BaseBlock.js';
6
+ import { BlockTemplate } from '../compiler/BlockTemplate.js';
7
+ export class TemplateBlock extends BaseBlock {
8
+ constructor(definition) {
9
+ super();
10
+ this.type = definition.type;
11
+ this.category = definition.category;
12
+ this.subcategory = definition.subcategory;
13
+ this.name = definition.name;
14
+ this.description = definition.description;
15
+ this.color = definition.color || '#607D8B';
16
+ this.width = definition.width || 200;
17
+ this._inputs = definition.inputs.map(i => ({
18
+ ...i
19
+ }));
20
+ this._outputs = definition.outputs.map(o => ({
21
+ ...o
22
+ }));
23
+ this._parameters = definition.parameters.map(p => {
24
+ const param = {
25
+ ...p,
26
+ type: p.type
27
+ };
28
+ // Add display metadata for the UI ONLY if not already specified in ATL
29
+ if (p.conversion === 'LOGFREQ') {
30
+ if (param.displayMin === undefined)
31
+ param.displayMin = p.min || 20;
32
+ if (param.displayMax === undefined)
33
+ param.displayMax = p.max || 5000;
34
+ if (param.displayUnit === undefined)
35
+ param.displayUnit = 'Hz';
36
+ }
37
+ else if (p.conversion === 'DBLEVEL') {
38
+ if (param.displayUnit === undefined)
39
+ param.displayUnit = 'dB';
40
+ }
41
+ return param;
42
+ });
43
+ this.templateEngine = new BlockTemplate(definition);
44
+ this.autoCalculateHeight();
45
+ }
46
+ getCustomLabel(params, ctx, blockId) {
47
+ // Try resolving template from definition
48
+ const dynamicLabel = this.templateEngine.resolveLabel(params, ctx, blockId);
49
+ // If an explicit label template was provided (even if empty ""), respect it and skip fallback
50
+ if (dynamicLabel !== null)
51
+ return dynamicLabel;
52
+ // Fallback to frequency heuristic (only if no explicit label template exists)
53
+ const freqParam = this._parameters.find(p => p.conversion === 'LOGFREQ');
54
+ if (freqParam) {
55
+ const val = params[freqParam.id] ?? freqParam.default;
56
+ const hz = typeof val === 'number' && val < 1.0 ? this.filterCoeffToHz(val) : val;
57
+ return `${Math.round(hz)} Hz`;
58
+ }
59
+ return null;
60
+ }
61
+ generateCode(ctx) {
62
+ const blockInstance = ctx.getBlock(ctx.getCurrentBlock());
63
+ const irNodes = this.templateEngine.generateIR(blockInstance, ctx);
64
+ for (const node of irNodes) {
65
+ ctx.pushIR(node);
66
+ }
67
+ }
68
+ getRawTemplate() {
69
+ const def = this.templateEngine.definition;
70
+ if (!def)
71
+ return undefined;
72
+ if (def._rawAtl) {
73
+ return def._rawAtl;
74
+ }
75
+ // Fallback: Reconstruct ATL string
76
+ const metadata = { ...def };
77
+ delete metadata.template;
78
+ delete metadata._rawAtl;
79
+ return `---\n${JSON.stringify(metadata, null, 4)}\n---\n${def.template}`;
80
+ }
81
+ }
82
+ //# sourceMappingURL=TemplateBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemplateBlock.js","sourceRoot":"","sources":["../../../src/blockDiagram/blocks/TemplateBlock.ts"],"names":[],"mappings":"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"}