@vessel-dsp/chain 0.1.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 (58) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +230 -0
  3. package/dist/chain.d.ts +31 -0
  4. package/dist/chain.d.ts.map +1 -0
  5. package/dist/chain.js +208 -0
  6. package/dist/chain.js.map +1 -0
  7. package/dist/index.d.ts +14 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +13 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/ir-resample.d.ts +2 -0
  12. package/dist/ir-resample.d.ts.map +1 -0
  13. package/dist/ir-resample.js +41 -0
  14. package/dist/ir-resample.js.map +1 -0
  15. package/dist/nam/engine.d.ts +73 -0
  16. package/dist/nam/engine.d.ts.map +1 -0
  17. package/dist/nam/engine.js +89 -0
  18. package/dist/nam/engine.js.map +1 -0
  19. package/dist/nodes/amp-shaper-node.d.ts +37 -0
  20. package/dist/nodes/amp-shaper-node.d.ts.map +1 -0
  21. package/dist/nodes/amp-shaper-node.js +134 -0
  22. package/dist/nodes/amp-shaper-node.js.map +1 -0
  23. package/dist/nodes/gain-node.d.ts +19 -0
  24. package/dist/nodes/gain-node.d.ts.map +1 -0
  25. package/dist/nodes/gain-node.js +49 -0
  26. package/dist/nodes/gain-node.js.map +1 -0
  27. package/dist/nodes/input-profile-node.d.ts +38 -0
  28. package/dist/nodes/input-profile-node.d.ts.map +1 -0
  29. package/dist/nodes/input-profile-node.js +245 -0
  30. package/dist/nodes/input-profile-node.js.map +1 -0
  31. package/dist/nodes/ir-node.d.ts +56 -0
  32. package/dist/nodes/ir-node.d.ts.map +1 -0
  33. package/dist/nodes/ir-node.js +438 -0
  34. package/dist/nodes/ir-node.js.map +1 -0
  35. package/dist/nodes/master-node.d.ts +23 -0
  36. package/dist/nodes/master-node.d.ts.map +1 -0
  37. package/dist/nodes/master-node.js +93 -0
  38. package/dist/nodes/master-node.js.map +1 -0
  39. package/dist/nodes/nam-node.d.ts +81 -0
  40. package/dist/nodes/nam-node.d.ts.map +1 -0
  41. package/dist/nodes/nam-node.js +234 -0
  42. package/dist/nodes/nam-node.js.map +1 -0
  43. package/dist/nodes/runtime-node.d.ts +66 -0
  44. package/dist/nodes/runtime-node.d.ts.map +1 -0
  45. package/dist/nodes/runtime-node.js +247 -0
  46. package/dist/nodes/runtime-node.js.map +1 -0
  47. package/dist/supply-profile.d.ts +56 -0
  48. package/dist/supply-profile.d.ts.map +1 -0
  49. package/dist/supply-profile.js +139 -0
  50. package/dist/supply-profile.js.map +1 -0
  51. package/dist/types.d.ts +66 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +22 -0
  54. package/dist/types.js.map +1 -0
  55. package/nam-engine/NOTICE.md +32 -0
  56. package/nam-engine/nam-engine.js +2 -0
  57. package/nam-engine/nam-engine.wasm +0 -0
  58. package/package.json +67 -0
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Battery supply profiles for {@link RuntimeNode.setSupplyProfile}.
3
+ *
4
+ * A profile is an open-circuit EMF magnitude plus a series resistance. It is
5
+ * applied to the circuit's external supply stamps only (see
6
+ * `resolveSupplyStamps` in `@vessel-dsp/compiler`): derived rails keep their
7
+ * compiled values, and mains-fed rails are refused. There is no audio-domain
8
+ * processing here: no envelope follower, no waveshaper, no extra chain node.
9
+ * The circuit's own current draw through the series resistance is what
10
+ * produces sag inside the solver.
11
+ *
12
+ * Provenance rule: every numeric value below is either the literal
13
+ * "definition" (the ideal source) or a citation of the one opened document,
14
+ * Jack Orman, "9v Battery Impedance", AMZ-FX Lab Notebook, copyright 2015,
15
+ * http://www.muzique.com/lab/batteryz.htm, method: unloaded reading with a
16
+ * Fluke multimeter, then loaded with a 560 ohm resistor, internal resistance
17
+ * by Ohm's law. No adapter profile is listed because no source was found for
18
+ * one (design note section 5). No number from the old PowerSupplyNode is
19
+ * reused.
20
+ */
21
+ const IDEAL = {
22
+ id: "ideal",
23
+ name: "Ideal supply",
24
+ openCircuitVolts: null,
25
+ internalResistanceOhms: 0,
26
+ source: "definition",
27
+ };
28
+ const ALKALINE_FRESH = {
29
+ id: "alkaline-fresh",
30
+ name: "Fresh alkaline",
31
+ openCircuitVolts: null,
32
+ // (5.99 + 4.82) / 2 = 10.81 / 2 = 5.405.
33
+ internalResistanceOhms: 5.405,
34
+ source: "Orman 2015 (http://www.muzique.com/lab/batteryz.htm), fresh table: " +
35
+ "AC-Delco alkaline #1 5.99 ohm and #2 4.82 ohm; " +
36
+ "value is their mean (5.99 + 4.82) / 2 = 5.405 ohm. " +
37
+ "Open-circuit volts null keeps the pedal's own declared supply voltage.",
38
+ };
39
+ const ZINC_CARBON_FRESH = {
40
+ id: "zinc-carbon-fresh",
41
+ name: "Fresh zinc-carbon",
42
+ openCircuitVolts: null,
43
+ // (25.28 + 26.57) / 2 = 51.85 / 2 = 25.925.
44
+ internalResistanceOhms: 25.925,
45
+ source: "Orman 2015 (http://www.muzique.com/lab/batteryz.htm), fresh table: " +
46
+ "Sunbeam Heavy Duty #1 25.28 ohm and #2 26.57 ohm; " +
47
+ "value is their mean (25.28 + 26.57) / 2 = 25.925 ohm. " +
48
+ "Open-circuit volts null keeps the pedal's own declared supply voltage.",
49
+ };
50
+ const ALKALINE_DEPLETED_SPECIMEN = {
51
+ id: "alkaline-depleted-specimen",
52
+ name: "Depleted alkaline specimen (single cell, not a type rating)",
53
+ openCircuitVolts: 7.73,
54
+ internalResistanceOhms: 195.0,
55
+ source: "Orman 2015 (http://www.muzique.com/lab/batteryz.htm), used table: " +
56
+ "Duracell alkaline #6, unloaded 7.73 V, loaded 6.43 V, 195.00 ohm. " +
57
+ "A single specimen, not a type rating.",
58
+ };
59
+ const ZINC_CARBON_USED_SPECIMEN = {
60
+ id: "zinc-carbon-used-specimen",
61
+ name: "Used zinc-carbon specimen (single cell, not a type rating)",
62
+ openCircuitVolts: 9.02,
63
+ internalResistanceOhms: 78.47,
64
+ source: "Orman 2015 (http://www.muzique.com/lab/batteryz.htm), used table: " +
65
+ "Golden Power Heavy Duty #7, unloaded 9.02 V, loaded 7.91 V, 78.47 ohm. " +
66
+ "A single specimen, not a type rating.",
67
+ };
68
+ /**
69
+ * The five built-in profiles, and only these. Adapter profiles are
70
+ * deliberately absent: no source was found for a regulated 9 V, regulated
71
+ * 18 V, or unregulated AC/DC resistance or voltage.
72
+ */
73
+ export const SUPPLY_PROFILES = [
74
+ IDEAL,
75
+ ALKALINE_FRESH,
76
+ ZINC_CARBON_FRESH,
77
+ ALKALINE_DEPLETED_SPECIMEN,
78
+ ZINC_CARBON_USED_SPECIMEN,
79
+ ];
80
+ function assertFinitePositive(value, label) {
81
+ if (!Number.isFinite(value) || value <= 0) {
82
+ throw new Error(`${label} must be a finite positive number, got ${String(value)}`);
83
+ }
84
+ }
85
+ /**
86
+ * Build a profile from the caller's own measurement, following Orman's
87
+ * method: read the open-circuit volts E, then the loaded volts across a known
88
+ * resistor Rload, and compute Rint = (Vopen - Vloaded) / (Vloaded / Rload).
89
+ */
90
+ export function profileFromMeasurement(input) {
91
+ const { openCircuitVolts, loadedVolts, loadOhms } = input;
92
+ assertFinitePositive(openCircuitVolts, "openCircuitVolts");
93
+ assertFinitePositive(loadedVolts, "loadedVolts");
94
+ assertFinitePositive(loadOhms, "loadOhms");
95
+ if (!(loadedVolts <= openCircuitVolts)) {
96
+ throw new Error(`loadedVolts (${String(loadedVolts)}) must not exceed openCircuitVolts (${String(openCircuitVolts)})`);
97
+ }
98
+ const current = loadedVolts / loadOhms;
99
+ const internalResistanceOhms = (openCircuitVolts - loadedVolts) / current;
100
+ if (!Number.isFinite(internalResistanceOhms) || internalResistanceOhms < 0) {
101
+ throw new Error(`measured internal resistance ${String(internalResistanceOhms)} is not a finite non-negative resistance`);
102
+ }
103
+ return {
104
+ id: "measured",
105
+ name: "Measured supply (caller measurement)",
106
+ openCircuitVolts,
107
+ internalResistanceOhms,
108
+ source: `Caller-supplied measurement by Orman's method (Orman 2015, ` +
109
+ `http://www.muzique.com/lab/batteryz.htm): open-circuit ` +
110
+ `${String(openCircuitVolts)} V, loaded ${String(loadedVolts)} V ` +
111
+ `across ${String(loadOhms)} ohm, ` +
112
+ `Rint = (Vopen - Vloaded) / (Vloaded / Rload) = ${String(internalResistanceOhms)} ohm.`,
113
+ };
114
+ }
115
+ /**
116
+ * Build a profile from caller-supplied numbers (for example a preset
117
+ * round-trip). The source is the caller: no citation is claimed.
118
+ */
119
+ export function customSupplyProfile(input) {
120
+ const { openCircuitVolts, internalResistanceOhms, name } = input;
121
+ if (openCircuitVolts !== null) {
122
+ if (!Number.isFinite(openCircuitVolts) || openCircuitVolts <= 0) {
123
+ throw new Error(`openCircuitVolts must be null or a finite positive number, got ${String(openCircuitVolts)}`);
124
+ }
125
+ }
126
+ if (!Number.isFinite(internalResistanceOhms) ||
127
+ internalResistanceOhms < 0) {
128
+ throw new Error(`internalResistanceOhms must be a finite non-negative resistance, got ${String(internalResistanceOhms)}`);
129
+ }
130
+ const trimmed = name?.trim() ?? "";
131
+ return {
132
+ id: "custom",
133
+ name: trimmed.length > 0 ? trimmed : "Custom supply",
134
+ openCircuitVolts,
135
+ internalResistanceOhms,
136
+ source: "caller-supplied",
137
+ };
138
+ }
139
+ //# sourceMappingURL=supply-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supply-profile.js","sourceRoot":"","sources":["../src/supply-profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ export type PickupType = "single-coil" | "humbucker" | "active" | "piezo" | "custom";
2
+ export interface InputProfileConfig {
3
+ pickupType: PickupType;
4
+ /** Input impedance in Ohms (e.g. 250000, 500000, 1000000) */
5
+ impedanceOhms: number;
6
+ /** Input trim gain in dB (-24 to +24 dB) */
7
+ inputGainDb: number;
8
+ /** Guitar to first pedal cable length in meters (default: 3m) */
9
+ guitarCableLengthMeters?: number;
10
+ /** Cable capacitance in pF/meter (default: 100 pF/m) */
11
+ cableCapacitancePfPerM?: number;
12
+ /** Resonant peak frequency in Hz (calculated from pickup inductance & cable capacitance) */
13
+ resonantFreqHz?: number;
14
+ /** Resonant peak Q factor */
15
+ resonantQ?: number;
16
+ }
17
+ export interface MasterConfig {
18
+ /** Master output volume in dB (-60 to +12 dB) */
19
+ volumeDb: number;
20
+ /** Master mute flag */
21
+ muted: boolean;
22
+ /** Enable soft-knee safety limiter to prevent harsh digital clipping */
23
+ limiter: boolean;
24
+ }
25
+ export interface ChainNode {
26
+ readonly id: string;
27
+ readonly name: string;
28
+ readonly kind: string;
29
+ bypassed: boolean;
30
+ mix: number;
31
+ prepare(sampleRate: number): void;
32
+ process(input: Float64Array | Float32Array): Float64Array;
33
+ reset(): void;
34
+ getParam(id: string): number | undefined;
35
+ setParam(id: string, value: number): void;
36
+ getParams(): Record<string, number>;
37
+ /**
38
+ * Release resources the node holds outside the chain -- a WASM instance, a file handle.
39
+ * Called on the node a chain drops: `removeNode`, `clearNodes`, and the replace-by-id path
40
+ * in `addNode`. Optional because most nodes hold nothing that outlives them.
41
+ */
42
+ dispose?(): void;
43
+ }
44
+ export interface NodeSnapshot {
45
+ id: string;
46
+ name: string;
47
+ kind: string;
48
+ bypassed: boolean;
49
+ mix: number;
50
+ params: Record<string, number>;
51
+ }
52
+ export interface ChainPreset {
53
+ name: string;
54
+ version: "1.0";
55
+ inputProfile: InputProfileConfig;
56
+ nodes: NodeSnapshot[];
57
+ master: MasterConfig;
58
+ }
59
+ export interface SignalChainOptions {
60
+ sampleRate?: number;
61
+ inputProfile?: Partial<InputProfileConfig>;
62
+ master?: Partial<MasterConfig>;
63
+ }
64
+ export type CableLengthPreset = "15cm" | "30cm" | "50cm" | "1m" | "3m" | "6m" | "10m" | number;
65
+ export declare function parseCableLengthMeters(value: CableLengthPreset | string | number | undefined, fallbackMeters?: number): number;
66
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GACnB,aAAa,GACb,WAAW,GACX,QAAQ,GACR,OAAO,GACP,QAAQ,CAAC;AAEZ,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,UAAU,CAAC;IACvB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,wDAAwD;IACxD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,YAAY,CAAC;IAC1D,KAAK,IAAI,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC;;;;OAIG;IACH,OAAO,CAAC,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,KAAK,CAAC;IACf,YAAY,EAAE,kBAAkB,CAAC;IACjC,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/B;AAED,MAAM,MAAM,iBAAiB,GAC1B,MAAM,GACN,MAAM,GACN,MAAM,GACN,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,MAAM,CAAC;AAEV,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,EACtD,cAAc,SAAM,GAClB,MAAM,CAkBR"}
package/dist/types.js ADDED
@@ -0,0 +1,22 @@
1
+ export function parseCableLengthMeters(value, fallbackMeters = 3.0) {
2
+ if (value === undefined || value === null)
3
+ return fallbackMeters;
4
+ if (typeof value === "number")
5
+ return Math.max(0, value);
6
+ const str = String(value).trim().toLowerCase();
7
+ if (str.endsWith("cm")) {
8
+ const val = parseFloat(str.slice(0, -2));
9
+ return Number.isFinite(val) ? val / 100 : fallbackMeters;
10
+ }
11
+ if (str.endsWith("m")) {
12
+ const val = parseFloat(str.slice(0, -1));
13
+ return Number.isFinite(val) ? val : fallbackMeters;
14
+ }
15
+ if (str.endsWith("ft")) {
16
+ const val = parseFloat(str.slice(0, -2));
17
+ return Number.isFinite(val) ? val * 0.3048 : fallbackMeters;
18
+ }
19
+ const num = parseFloat(str);
20
+ return Number.isFinite(num) ? num : fallbackMeters;
21
+ }
22
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAqFA,MAAM,UAAU,sBAAsB,CACrC,KAAsD,EACtD,cAAc,GAAG,GAAG;IAEpB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,cAAc,CAAC;IACjE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;IAC1D,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;IACpD,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC;IAC7D,CAAC;IACD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;AACpD,CAAC"}
@@ -0,0 +1,32 @@
1
+ # NAM engine — third-party notices
2
+
3
+ `nam-engine.js` and `nam-engine.wasm` are **build outputs**, not sources. They are produced
4
+ by `scripts/build-nam-engine.sh`, which pins the exact upstream revisions below. Rebuild rather than
5
+ hand-edit.
6
+
7
+ | component | revision | licence |
8
+ |---|---|---|
9
+ | [tone-3000/neural-amp-modeler-wasm](https://github.com/tone-3000/neural-amp-modeler-wasm) (the `nam-engine` target) | `a6c895049771bacc40c74dfa19369c2ebf75cdb1` | MIT, © 2026 TONE3000 |
10
+ | [sdatkinson/NeuralAmpModelerCore](https://github.com/sdatkinson/NeuralAmpModelerCore) v0.5.4 | `1f42f88535884450104b8711d7595019afa0495b` | MIT, © 2023 Steven Atkinson |
11
+ | [Eigen](https://eigen.tuxfamily.org) (header-only, statically linked) | `bc3b39870ecb690a623a3f49149a358b95c5781d` | MPL2 primarily; see the project's `COPYING.README` |
12
+ | [nlohmann/json](https://github.com/nlohmann/json) (header-only) | vendored by the core above | MIT |
13
+
14
+ ## Vendored artifact checksums
15
+
16
+ | file | sha256 |
17
+ |---|---|
18
+ | `nam-engine.wasm` | `f0f84866bcf54b175d93f5627a8c48581e6a2bbcd052ca883b57167f823d1d86` |
19
+ | `nam-engine.js` | `1c4463155b847770dd265c35daa6fe63c70978994d3624ebd71279f29c774e79` |
20
+
21
+ MIT requires its copyright and permission notice to travel with copies and substantial portions of
22
+ the software, which is why this file sits beside the artifacts and is listed in the package's
23
+ `files`. Eigen is MPL2, which is file-level weak copyleft: statically linking it imposes no
24
+ condition on the combined work, and only modifications to Eigen's own files would need publishing.
25
+ We modify none. Eigen also ships a handful of LGPL-licensed files that `EIGEN_MPL2_ONLY` excludes;
26
+ the upstream build does not set it, and the `nam-engine` target does not reference those components.
27
+
28
+ ## Model files are not bundled
29
+
30
+ The engine is vendored; `.nam` model files are not. Models are third-party captures whose
31
+ licences are their authors' -- it is the user's responsibility to supply models they are licensed
32
+ to use. The package ships no model and the node takes the model's JSON text from the caller.
@@ -0,0 +1,2 @@
1
+ async function createNamEngine(moduleArg={}){var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var thisProgram="./this.program";var _scriptName=import.meta.url;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var runtimeInitialized=false;function getMemoryBuffer(){return wasmMemory.buffer}function updateMemoryViews(){if(HEAP8?.buffer?.resizable)return;var b=getMemoryBuffer();HEAP8=new Int8Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b)}function preRun(){}function initRuntime(){runtimeInitialized=true;wasmExports["k"]()}function postRun(){}function abort(what){what=`Aborted(${what})`;err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";if(runtimeInitialized){___trap()}var e=new WebAssembly.RuntimeError(what);throw e}var wasmBinaryFile;function findWasmBinary(){if(Module["locateFile"]){return locateFile("nam-engine.wasm")}return new URL("nam-engine.wasm",import.meta.url).href}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();var instantiateWasm=Module["instantiateWasm"];if(instantiateWasm){return new Promise(resolve=>{instantiateWasm(info,inst=>resolve(receiveInstance(inst)))})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var HEAP8;var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str};var HEAPU8;var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var ___assert_fail=(condition,filename,line,func)=>abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"]);var __abort_js=()=>abort("");var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.codePointAt(i);if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var HEAP32;var HEAPU32;var getHeapMax=()=>536870912;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var ENV={};var getExecutableName=()=>thisProgram;var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(globalThis.navigator?.language??"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;var envp=0;for(var string of getEnvStrings()){var ptr=environ_buf+bufSize;HEAPU32[__environ+envp>>2]=ptr;bufSize+=stringToUTF8(string,ptr,Infinity)+1;envp+=4}return 0};var lengthBytesUTF8=str=>{var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;for(var string of strings){bufSize+=lengthBytesUTF8(string)+1}HEAPU32[penviron_buf_size>>2]=bufSize;return 0};var _fd_close=fd=>52;var _fd_read=(fd,iov,iovcnt,pnum)=>52;var INT53_MAX=9007199254740992;var INT53_MIN=-9007199254740992;var bigintToI53Checked=num=>num<INT53_MIN||num>INT53_MAX?NaN:Number(num);function _fd_seek(fd,offset,whence,newOffset){offset=bigintToI53Checked(offset);return 70}var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(!curr||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j<len;j++){printChar(fd,HEAPU8[ptr+j])}num+=len}HEAPU32[pnum>>2]=num;return 0};var HEAPF32;{if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"]}Module["UTF8ToString"]=UTF8ToString;Module["stringToUTF8"]=stringToUTF8;Module["lengthBytesUTF8"]=lengthBytesUTF8;var _nam_createInstance,_nam_destroyInstance,_nam_loadModel,_nam_unloadModel,_nam_hasModel,_nam_getBuffer,_nam_process,_nam_isSlimmable,_nam_setSlimmableSize,_nam_getSlimmableBreakpointCount,_nam_getSlimmableBreakpoint,_nam_hasLoudness,_nam_getLoudness,_nam_getExpectedSampleRate,_nam_getLastError,_nam_getVersion,_free,_malloc,___trap,memory,__indirect_function_table,wasmMemory;function assignWasmExports(wasmExports){_nam_createInstance=Module["_nam_createInstance"]=wasmExports["l"];_nam_destroyInstance=Module["_nam_destroyInstance"]=wasmExports["m"];_nam_loadModel=Module["_nam_loadModel"]=wasmExports["n"];_nam_unloadModel=Module["_nam_unloadModel"]=wasmExports["o"];_nam_hasModel=Module["_nam_hasModel"]=wasmExports["p"];_nam_getBuffer=Module["_nam_getBuffer"]=wasmExports["q"];_nam_process=Module["_nam_process"]=wasmExports["r"];_nam_isSlimmable=Module["_nam_isSlimmable"]=wasmExports["s"];_nam_setSlimmableSize=Module["_nam_setSlimmableSize"]=wasmExports["t"];_nam_getSlimmableBreakpointCount=Module["_nam_getSlimmableBreakpointCount"]=wasmExports["u"];_nam_getSlimmableBreakpoint=Module["_nam_getSlimmableBreakpoint"]=wasmExports["v"];_nam_hasLoudness=Module["_nam_hasLoudness"]=wasmExports["w"];_nam_getLoudness=Module["_nam_getLoudness"]=wasmExports["x"];_nam_getExpectedSampleRate=Module["_nam_getExpectedSampleRate"]=wasmExports["y"];_nam_getLastError=Module["_nam_getLastError"]=wasmExports["z"];_nam_getVersion=Module["_nam_getVersion"]=wasmExports["A"];_free=Module["_free"]=wasmExports["B"];_malloc=Module["_malloc"]=wasmExports["C"];___trap=wasmExports["D"];memory=wasmMemory=wasmExports["j"];__indirect_function_table=wasmExports["__indirect_function_table"]}var wasmImports={a:___assert_fail,i:__abort_js,h:_emscripten_resize_heap,c:_environ_get,d:_environ_sizes_get,e:_fd_close,f:_fd_read,g:_fd_seek,b:_fd_write};async function run(){preRun();if(ABORT)return;initRuntime();Module["onRuntimeInitialized"]?.();postRun()}var wasmExports;wasmExports=await createWasm();await run();
2
+ ;return Module}export default createNamEngine;
Binary file
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@vessel-dsp/chain",
3
+ "version": "0.1.0",
4
+ "description": "Headless audio signal chain graph engine for VesselDSP circuits, guitar profiling, amp shaping, and cabinet IRs.",
5
+ "keywords": [
6
+ "dsp",
7
+ "audio",
8
+ "signal-chain",
9
+ "guitar",
10
+ "ir",
11
+ "impulse-response",
12
+ "vessel-dsp"
13
+ ],
14
+ "homepage": "https://vessel-dsp.github.io/core/",
15
+ "bugs": {
16
+ "url": "https://github.com/vessel-dsp/core/issues"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/vessel-dsp/core.git"
21
+ },
22
+ "license": "MIT",
23
+ "sideEffects": false,
24
+ "type": "module",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "bun": "./dist/index.js",
29
+ "import": "./dist/index.js"
30
+ },
31
+ "./ir-resample": {
32
+ "types": "./dist/ir-resample.d.ts",
33
+ "bun": "./dist/ir-resample.js",
34
+ "import": "./dist/ir-resample.js"
35
+ },
36
+ "./nam-engine.wasm": "./nam-engine/nam-engine.wasm",
37
+ "./nam-engine.js": "./nam-engine/nam-engine.js",
38
+ "./nam-engine.NOTICE.md": "./nam-engine/NOTICE.md",
39
+ "./package.json": {
40
+ "default": "./package.json"
41
+ }
42
+ },
43
+ "main": "./dist/index.js",
44
+ "module": "./dist/index.js",
45
+ "types": "./dist/index.d.ts",
46
+ "files": [
47
+ "dist",
48
+ "nam-engine",
49
+ "README.md",
50
+ "LICENSE.md"
51
+ ],
52
+ "scripts": {
53
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && bun run ../../scripts/fix-dist-imports.ts dist",
54
+ "clean": "rm -rf dist",
55
+ "prepack": "bun run --cwd ../core build && bun run --cwd ../compiler build && bun run --cwd ../runtime build:wasm && bun run --cwd ../runtime build && bun run build",
56
+ "pack:dry-run": "npm pack --dry-run",
57
+ "typecheck": "tsc --noEmit -p tsconfig.json"
58
+ },
59
+ "dependencies": {
60
+ "@vessel-dsp/compiler": "0.2.0",
61
+ "@vessel-dsp/core": "0.16.0",
62
+ "@vessel-dsp/runtime": "0.2.0"
63
+ },
64
+ "publishConfig": {
65
+ "access": "public"
66
+ }
67
+ }