@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.
- package/LICENSE.md +21 -0
- package/README.md +230 -0
- package/dist/chain.d.ts +31 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +208 -0
- package/dist/chain.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/ir-resample.d.ts +2 -0
- package/dist/ir-resample.d.ts.map +1 -0
- package/dist/ir-resample.js +41 -0
- package/dist/ir-resample.js.map +1 -0
- package/dist/nam/engine.d.ts +73 -0
- package/dist/nam/engine.d.ts.map +1 -0
- package/dist/nam/engine.js +89 -0
- package/dist/nam/engine.js.map +1 -0
- package/dist/nodes/amp-shaper-node.d.ts +37 -0
- package/dist/nodes/amp-shaper-node.d.ts.map +1 -0
- package/dist/nodes/amp-shaper-node.js +134 -0
- package/dist/nodes/amp-shaper-node.js.map +1 -0
- package/dist/nodes/gain-node.d.ts +19 -0
- package/dist/nodes/gain-node.d.ts.map +1 -0
- package/dist/nodes/gain-node.js +49 -0
- package/dist/nodes/gain-node.js.map +1 -0
- package/dist/nodes/input-profile-node.d.ts +38 -0
- package/dist/nodes/input-profile-node.d.ts.map +1 -0
- package/dist/nodes/input-profile-node.js +245 -0
- package/dist/nodes/input-profile-node.js.map +1 -0
- package/dist/nodes/ir-node.d.ts +56 -0
- package/dist/nodes/ir-node.d.ts.map +1 -0
- package/dist/nodes/ir-node.js +438 -0
- package/dist/nodes/ir-node.js.map +1 -0
- package/dist/nodes/master-node.d.ts +23 -0
- package/dist/nodes/master-node.d.ts.map +1 -0
- package/dist/nodes/master-node.js +93 -0
- package/dist/nodes/master-node.js.map +1 -0
- package/dist/nodes/nam-node.d.ts +81 -0
- package/dist/nodes/nam-node.d.ts.map +1 -0
- package/dist/nodes/nam-node.js +234 -0
- package/dist/nodes/nam-node.js.map +1 -0
- package/dist/nodes/runtime-node.d.ts +66 -0
- package/dist/nodes/runtime-node.d.ts.map +1 -0
- package/dist/nodes/runtime-node.js +247 -0
- package/dist/nodes/runtime-node.js.map +1 -0
- package/dist/supply-profile.d.ts +56 -0
- package/dist/supply-profile.d.ts.map +1 -0
- package/dist/supply-profile.js +139 -0
- package/dist/supply-profile.js.map +1 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/nam-engine/NOTICE.md +32 -0
- package/nam-engine/nam-engine.js +2 -0
- package/nam-engine/nam-engine.wasm +0 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nam-node.d.ts","sourceRoot":"","sources":["../../src/nodes/nam-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC7B,gGAAgG;IAChG,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,sEAAsE;IACtE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC3B,+FAA+F;IAC/F,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,yEAAyE;IACzE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,gGAAgG;IAChG,QAAQ,CAAC,oBAAoB,EAAE,MAAM,EAAE,CAAC;CACxC;AAOD;;;;;;;;;;GAUG;AACH,qBAAa,OAAQ,YAAW,SAAS;IACxC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,SAAS;IACtB,uFAAuF;IACvF,QAAQ,CAAC,cAAc,KAAK;IAC5B,QAAQ,UAAS;IACjB,GAAG,SAAO;IAEV,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,IAAI,CAA6B;IAEzC,OAAO,CAAC,QAAQ,CAA0D;IAC1E,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,oBAAoB,CAAgB;gBAEhC,EAAE,oBAAY,EAAE,IAAI,oBAAY,EAAE,MAAM,EAAE,aAAa;IAUnE,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAMjC,KAAK,IAAI,IAAI;IAMb,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAexC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAmBzC,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IASnC,OAAO,IAAI,WAAW;IAStB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQjC,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,YAAY;IAkCzD,OAAO,IAAI,IAAI;IAIf;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA2B5B,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,eAAe;CAYvB"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { loadNamModel, namLoudness, } from "../nam/engine.js";
|
|
2
|
+
const MAX_FRAMES = 1024;
|
|
3
|
+
const GAIN_DB_LIMIT = 24;
|
|
4
|
+
/** A model stating a rate this far from the chain rate is refused, not run silently. */
|
|
5
|
+
const SAMPLE_RATE_TOLERANCE_HZ = 0.5;
|
|
6
|
+
/**
|
|
7
|
+
* A NAM (Neural Amp Modeler) capture as a chain node.
|
|
8
|
+
*
|
|
9
|
+
* **The node applies no loudness gain of its own, deliberately.** `nam_process` already implements
|
|
10
|
+
* NAM's `Normalized` output mode internally -- `10^((-18 - modelLoudness)/20)`, smoothed against
|
|
11
|
+
* clicks -- which is the policy the workbench validated by listening. Applying it again here would
|
|
12
|
+
* double it. `getInfo().loudness` reports what the engine did so a host can show it.
|
|
13
|
+
*
|
|
14
|
+
* The engine instance is created at `prepare`, not in the constructor, because instantiation is
|
|
15
|
+
* asynchronous and belongs to the caller. Until then the node passes audio through.
|
|
16
|
+
*/
|
|
17
|
+
export class NamNode {
|
|
18
|
+
id;
|
|
19
|
+
name;
|
|
20
|
+
kind = "nam";
|
|
21
|
+
/** The engine adds no algorithmic delay; the buffer is in-place and sample-aligned. */
|
|
22
|
+
latencySamples = 0;
|
|
23
|
+
bypassed = false;
|
|
24
|
+
mix = 1.0;
|
|
25
|
+
engine;
|
|
26
|
+
modelJson;
|
|
27
|
+
slimSize;
|
|
28
|
+
inputGainDb;
|
|
29
|
+
outputGainDb;
|
|
30
|
+
sampleRate = 48000;
|
|
31
|
+
instanceId = 0;
|
|
32
|
+
bufferPointer = 0;
|
|
33
|
+
view = null;
|
|
34
|
+
loudness = { modelLoudnessDb: null, appliedGain: 1 };
|
|
35
|
+
expectedSampleRate = null;
|
|
36
|
+
slimmable = false;
|
|
37
|
+
slimmableBreakpoints = [];
|
|
38
|
+
constructor(id = "nam-amp", name = "NAM Amp", config) {
|
|
39
|
+
this.id = id;
|
|
40
|
+
this.name = name;
|
|
41
|
+
this.engine = config.engine;
|
|
42
|
+
this.modelJson = config.model;
|
|
43
|
+
this.slimSize = config.slimSize ?? -1;
|
|
44
|
+
this.inputGainDb = clampGainDb(config.inputGainDb ?? 0);
|
|
45
|
+
this.outputGainDb = clampGainDb(config.outputGainDb ?? 0);
|
|
46
|
+
}
|
|
47
|
+
prepare(sampleRate) {
|
|
48
|
+
this.sampleRate = sampleRate;
|
|
49
|
+
this.destroyInstance();
|
|
50
|
+
this.adoptInstance(this.createLoadedInstance(this.modelJson));
|
|
51
|
+
}
|
|
52
|
+
reset() {
|
|
53
|
+
// Recreating the instance is what "reload the state" means for this node: the engine's
|
|
54
|
+
// prewarm settles the network's initial conditions, which is the point of a reset.
|
|
55
|
+
this.prepare(this.sampleRate);
|
|
56
|
+
}
|
|
57
|
+
getParam(id) {
|
|
58
|
+
switch (id) {
|
|
59
|
+
case "inputGainDb":
|
|
60
|
+
return this.inputGainDb;
|
|
61
|
+
case "outputGainDb":
|
|
62
|
+
return this.outputGainDb;
|
|
63
|
+
case "slimSize":
|
|
64
|
+
// Not a param the engine will act on for this model, so it is not reported as
|
|
65
|
+
// one: a host that offered it would be offering a control that does nothing.
|
|
66
|
+
return this.slimmable ? this.slimSize : undefined;
|
|
67
|
+
default:
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
setParam(id, value) {
|
|
72
|
+
switch (id) {
|
|
73
|
+
case "inputGainDb":
|
|
74
|
+
this.inputGainDb = clampGainDb(value);
|
|
75
|
+
break;
|
|
76
|
+
case "outputGainDb":
|
|
77
|
+
this.outputGainDb = clampGainDb(value);
|
|
78
|
+
break;
|
|
79
|
+
case "slimSize":
|
|
80
|
+
// Ignored for non-slimmable models, and ignored rather than refused: the
|
|
81
|
+
// parameter is a host-level control that only some models answer to.
|
|
82
|
+
if (this.slimmable) {
|
|
83
|
+
this.slimSize = value;
|
|
84
|
+
this.engine._nam_setSlimmableSize(this.instanceId, value);
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
getParams() {
|
|
90
|
+
const params = {
|
|
91
|
+
inputGainDb: this.inputGainDb,
|
|
92
|
+
outputGainDb: this.outputGainDb,
|
|
93
|
+
};
|
|
94
|
+
if (this.slimmable)
|
|
95
|
+
params.slimSize = this.slimSize;
|
|
96
|
+
return params;
|
|
97
|
+
}
|
|
98
|
+
getInfo() {
|
|
99
|
+
return {
|
|
100
|
+
loudness: { ...this.loudness },
|
|
101
|
+
expectedSampleRate: this.expectedSampleRate,
|
|
102
|
+
slimmable: this.slimmable,
|
|
103
|
+
slimmableBreakpoints: [...this.slimmableBreakpoints],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Swap the model. The replacement is loaded into a **new** instance; the current one keeps
|
|
108
|
+
* running until the new one is ready, and is released only then. A refused model therefore
|
|
109
|
+
* never interrupts playback -- the engine's own reason is thrown and the old model stays.
|
|
110
|
+
*/
|
|
111
|
+
setModel(modelJson) {
|
|
112
|
+
const instanceId = this.createLoadedInstance(modelJson);
|
|
113
|
+
const previous = this.instanceId;
|
|
114
|
+
this.modelJson = modelJson;
|
|
115
|
+
this.adoptInstance(instanceId);
|
|
116
|
+
if (previous > 0)
|
|
117
|
+
this.engine._nam_destroyInstance(previous);
|
|
118
|
+
}
|
|
119
|
+
process(input) {
|
|
120
|
+
const length = input.length;
|
|
121
|
+
if (this.bypassed || this.instanceId <= 0) {
|
|
122
|
+
return new Float64Array(input);
|
|
123
|
+
}
|
|
124
|
+
const output = new Float64Array(length);
|
|
125
|
+
const inputGain = 10 ** (this.inputGainDb / 20);
|
|
126
|
+
const outputGain = 10 ** (this.outputGainDb / 20);
|
|
127
|
+
const wetMix = Math.max(0, Math.min(1, this.mix));
|
|
128
|
+
const dryMix = 1 - wetMix;
|
|
129
|
+
const engine = this.engine;
|
|
130
|
+
for (let offset = 0; offset < length; offset += MAX_FRAMES) {
|
|
131
|
+
const frames = Math.min(MAX_FRAMES, length - offset);
|
|
132
|
+
// Re-derived only when the heap identity changes. `ALLOW_MEMORY_GROWTH` means a growth
|
|
133
|
+
// detaches every existing view, and a detached `Float32Array` reads as zeros rather
|
|
134
|
+
// than throwing -- so the check is an identity comparison, not a try/catch.
|
|
135
|
+
const heap = this.bufferView();
|
|
136
|
+
for (let i = 0; i < frames; i++) {
|
|
137
|
+
heap[i] = (input[offset + i] ?? 0) * inputGain;
|
|
138
|
+
}
|
|
139
|
+
engine._nam_process(this.instanceId, frames);
|
|
140
|
+
// `nam_process` never allocates, so the view above is still attached here.
|
|
141
|
+
for (let i = 0; i < frames; i++) {
|
|
142
|
+
const wet = (heap[i] ?? 0) * outputGain;
|
|
143
|
+
const dry = input[offset + i] ?? 0;
|
|
144
|
+
output[offset + i] = dryMix * dry + wetMix * wet;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return output;
|
|
148
|
+
}
|
|
149
|
+
dispose() {
|
|
150
|
+
this.destroyInstance();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Create an instance with `modelJson` loaded, or throw. The instance is released on every
|
|
154
|
+
* failure path so a refused model does not strand one.
|
|
155
|
+
*/
|
|
156
|
+
createLoadedInstance(modelJson) {
|
|
157
|
+
const instanceId = this.engine._nam_createInstance(this.sampleRate, MAX_FRAMES);
|
|
158
|
+
if (instanceId <= 0) {
|
|
159
|
+
throw new Error("nam_createInstance refused");
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
loadNamModel(this.engine, instanceId, modelJson, this.slimSize);
|
|
163
|
+
const expected = this.engine._nam_getExpectedSampleRate(instanceId);
|
|
164
|
+
if (expected >= 0 &&
|
|
165
|
+
Math.abs(expected - this.sampleRate) > SAMPLE_RATE_TOLERANCE_HZ) {
|
|
166
|
+
throw new Error(`NAM model ${labelOf(modelJson)} states ${expected} Hz but the chain runs at ` +
|
|
167
|
+
`${this.sampleRate} Hz; refusing to run it at the wrong rate`);
|
|
168
|
+
}
|
|
169
|
+
return instanceId;
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
this.engine._nam_destroyInstance(instanceId);
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
adoptInstance(instanceId) {
|
|
177
|
+
this.instanceId = instanceId;
|
|
178
|
+
this.bufferPointer = this.engine._nam_getBuffer(instanceId);
|
|
179
|
+
this.view = null;
|
|
180
|
+
this.loudness = namLoudness(this.engine, instanceId);
|
|
181
|
+
const expected = this.engine._nam_getExpectedSampleRate(instanceId);
|
|
182
|
+
this.expectedSampleRate = expected < 0 ? null : expected;
|
|
183
|
+
this.slimmable = this.engine._nam_isSlimmable(instanceId) === 1;
|
|
184
|
+
this.slimmableBreakpoints = [];
|
|
185
|
+
if (this.slimmable) {
|
|
186
|
+
const count = this.engine._nam_getSlimmableBreakpointCount(instanceId);
|
|
187
|
+
for (let index = 0; index < count; index++) {
|
|
188
|
+
const breakpoint = this.engine._nam_getSlimmableBreakpoint(instanceId, index);
|
|
189
|
+
if (breakpoint >= 0)
|
|
190
|
+
this.slimmableBreakpoints.push(breakpoint);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
bufferView() {
|
|
195
|
+
if (this.view === null || this.view.buffer !== this.engine.HEAPF32.buffer) {
|
|
196
|
+
const offset = this.bufferPointer >> 2;
|
|
197
|
+
this.view = this.engine.HEAPF32.subarray(offset, offset + MAX_FRAMES);
|
|
198
|
+
}
|
|
199
|
+
return this.view;
|
|
200
|
+
}
|
|
201
|
+
destroyInstance() {
|
|
202
|
+
if (this.instanceId > 0) {
|
|
203
|
+
this.engine._nam_destroyInstance(this.instanceId);
|
|
204
|
+
}
|
|
205
|
+
this.instanceId = 0;
|
|
206
|
+
this.bufferPointer = 0;
|
|
207
|
+
this.view = null;
|
|
208
|
+
this.loudness = { modelLoudnessDb: null, appliedGain: 1 };
|
|
209
|
+
this.expectedSampleRate = null;
|
|
210
|
+
this.slimmable = false;
|
|
211
|
+
this.slimmableBreakpoints = [];
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function clampGainDb(value) {
|
|
215
|
+
return Math.max(-GAIN_DB_LIMIT, Math.min(GAIN_DB_LIMIT, value));
|
|
216
|
+
}
|
|
217
|
+
/** A short, stable label for a model document, for error messages. */
|
|
218
|
+
function labelOf(modelJson) {
|
|
219
|
+
try {
|
|
220
|
+
const parsed = JSON.parse(modelJson);
|
|
221
|
+
if (typeof parsed === "object" &&
|
|
222
|
+
parsed !== null &&
|
|
223
|
+
"name" in parsed &&
|
|
224
|
+
typeof parsed.name === "string" &&
|
|
225
|
+
parsed.name.length > 0) {
|
|
226
|
+
return parsed.name;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
// Not parseable, or has no name: fall through to the truncated document.
|
|
231
|
+
}
|
|
232
|
+
return `${modelJson.slice(0, 80)}...`;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=nam-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nam-node.js","sourceRoot":"","sources":["../../src/nodes/nam-node.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,WAAW,GAGX,MAAM,kBAAkB,CAAC;AA2B1B,MAAM,UAAU,GAAG,IAAI,CAAC;AACxB,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,wFAAwF;AACxF,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAErC;;;;;;;;;;GAUG;AACH,MAAM,OAAO,OAAO;IACV,EAAE,CAAS;IACX,IAAI,CAAS;IACb,IAAI,GAAG,KAAK,CAAC;IACtB,uFAAuF;IAC9E,cAAc,GAAG,CAAC,CAAC;IAC5B,QAAQ,GAAG,KAAK,CAAC;IACjB,GAAG,GAAG,GAAG,CAAC;IAEO,MAAM,CAAkB;IACjC,SAAS,CAAS;IAClB,QAAQ,CAAS;IACjB,WAAW,CAAS;IACpB,YAAY,CAAS;IAErB,UAAU,GAAG,KAAK,CAAC;IACnB,UAAU,GAAG,CAAC,CAAC;IACf,aAAa,GAAG,CAAC,CAAC;IAClB,IAAI,GAAwB,IAAI,CAAC;IAEjC,QAAQ,GAAgB,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IAClE,kBAAkB,GAAkB,IAAI,CAAC;IACzC,SAAS,GAAG,KAAK,CAAC;IAClB,oBAAoB,GAAa,EAAE,CAAC;IAE5C,YAAY,EAAE,GAAG,SAAS,EAAE,IAAI,GAAG,SAAS,EAAE,MAAqB;QAClE,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,CAAC,UAAkB;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK;QACJ,uFAAuF;QACvF,mFAAmF;QACnF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;IAED,QAAQ,CAAC,EAAU;QAClB,QAAQ,EAAE,EAAE,CAAC;YACZ,KAAK,aAAa;gBACjB,OAAO,IAAI,CAAC,WAAW,CAAC;YACzB,KAAK,cAAc;gBAClB,OAAO,IAAI,CAAC,YAAY,CAAC;YAC1B,KAAK,UAAU;gBACd,8EAA8E;gBAC9E,6EAA6E;gBAC7E,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YACnD;gBACC,OAAO,SAAS,CAAC;QACnB,CAAC;IACF,CAAC;IAED,QAAQ,CAAC,EAAU,EAAE,KAAa;QACjC,QAAQ,EAAE,EAAE,CAAC;YACZ,KAAK,aAAa;gBACjB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;gBACtC,MAAM;YACP,KAAK,cAAc;gBAClB,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;gBACvC,MAAM;YACP,KAAK,UAAU;gBACd,yEAAyE;gBACzE,qEAAqE;gBACrE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACpB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;oBACtB,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;gBAC3D,CAAC;gBACD,MAAM;QACR,CAAC;IACF,CAAC;IAED,SAAS;QACR,MAAM,MAAM,GAA2B;YACtC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;SAC/B,CAAC;QACF,IAAI,IAAI,CAAC,SAAS;YAAE,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QACpD,OAAO,MAAM,CAAC;IACf,CAAC;IAED,OAAO;QACN,OAAO;YACN,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE;YAC9B,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,oBAAoB,EAAE,CAAC,GAAG,IAAI,CAAC,oBAAoB,CAAC;SACpD,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,SAAiB;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QAC/B,IAAI,QAAQ,GAAG,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,CAAC,KAAkC;QACzC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC;YAC3C,OAAO,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3B,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,IAAI,UAAU,EAAE,CAAC;YAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;YACrD,uFAAuF;YACvF,oFAAoF;YACpF,4EAA4E;YAC5E,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACjC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;YAChD,CAAC;YACD,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC7C,2EAA2E;YAC3E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACjC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,UAAU,CAAC;gBACxC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;gBACnC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,GAAG,CAAC;YAClD,CAAC;QACF,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;IAED,OAAO;QACN,IAAI,CAAC,eAAe,EAAE,CAAC;IACxB,CAAC;IAED;;;OAGG;IACK,oBAAoB,CAAC,SAAiB;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,mBAAmB,CACjD,IAAI,CAAC,UAAU,EACf,UAAU,CACV,CAAC;QACF,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC;YACJ,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,0BAA0B,CAAC,UAAU,CAAC,CAAC;YACpE,IACC,QAAQ,IAAI,CAAC;gBACb,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,wBAAwB,EAC9D,CAAC;gBACF,MAAM,IAAI,KAAK,CACd,aAAa,OAAO,CAAC,SAAS,CAAC,WAAW,QAAQ,4BAA4B;oBAC7E,GAAG,IAAI,CAAC,UAAU,2CAA2C,CAC9D,CAAC;YACH,CAAC;YACD,OAAO,UAAU,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;YAC7C,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAEO,aAAa,CAAC,UAAkB;QACvC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,0BAA0B,CAAC,UAAU,CAAC,CAAC;QACpE,IAAI,CAAC,kBAAkB,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAChE,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,gCAAgC,CAAC,UAAU,CAAC,CAAC;YACvE,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,2BAA2B,CACzD,UAAU,EACV,KAAK,CACL,CAAC;gBACF,IAAI,UAAU,IAAI,CAAC;oBAAE,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACjE,CAAC;QACF,CAAC;IACF,CAAC;IAEO,UAAU;QACjB,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC;YACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IAClB,CAAC;IAEO,eAAe;QACtB,IAAI,IAAI,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;QAC1D,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC;IAChC,CAAC;CACD;AAED,SAAS,WAAW,CAAC,KAAa;IACjC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,sEAAsE;AACtE,SAAS,OAAO,CAAC,SAAiB;IACjC,IAAI,CAAC;QACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9C,IACC,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,KAAK,IAAI;YACf,MAAM,IAAI,MAAM;YAChB,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;YAC/B,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EACrB,CAAC;YACF,OAAO,MAAM,CAAC,IAAI,CAAC;QACpB,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,yEAAyE;IAC1E,CAAC;IACD,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Program, SupplyResolution } from "@vessel-dsp/compiler";
|
|
2
|
+
import type { SupplyProfile } from "../supply-profile.js";
|
|
3
|
+
import type { ChainNode } from "../types.js";
|
|
4
|
+
export type RuntimeNodeOptions = {
|
|
5
|
+
readonly source?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare class RuntimeNode implements ChainNode {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly kind = "circuit-runtime";
|
|
11
|
+
bypassed: boolean;
|
|
12
|
+
mix: number;
|
|
13
|
+
private runtime;
|
|
14
|
+
private program;
|
|
15
|
+
private params;
|
|
16
|
+
private sampleRate;
|
|
17
|
+
private source;
|
|
18
|
+
private supplyResolution;
|
|
19
|
+
private supplyProfile;
|
|
20
|
+
private appliedVoltsMagnitude;
|
|
21
|
+
private appliedOhms;
|
|
22
|
+
constructor(id: string, name: string, program: Program, options?: RuntimeNodeOptions);
|
|
23
|
+
getProgram(): Program;
|
|
24
|
+
/**
|
|
25
|
+
* Apply a supply profile to the circuit's external supply stamps.
|
|
26
|
+
*
|
|
27
|
+
* Resolves once (lazily, cached) with `resolveSupplyStamps(source,
|
|
28
|
+
* program)`, then retargets every resolved stamp through the runtime's
|
|
29
|
+
* `setSupply`. A null `openCircuitVolts` keeps each stamp's compiled
|
|
30
|
+
* magnitude; an explicit value replaces the magnitude. The sign always
|
|
31
|
+
* follows the stamp's own volts sign read from `getSupplies()`, so a
|
|
32
|
+
* positive-ground germanium rail stays negative.
|
|
33
|
+
*
|
|
34
|
+
* Throws when no source text was given or when nothing resolves, naming
|
|
35
|
+
* the refusal reason codes and rail ids. A program with refused derived
|
|
36
|
+
* rails but one resolved external rail applies to the resolved one and
|
|
37
|
+
* keeps the refusals visible via `getSupplyResolution()`.
|
|
38
|
+
*
|
|
39
|
+
* Callable before and after `prepare()` and between `process()` calls,
|
|
40
|
+
* following the runtime's contract. There is no audio-domain processing
|
|
41
|
+
* in this path.
|
|
42
|
+
*/
|
|
43
|
+
setSupplyProfile(profile: SupplyProfile): void;
|
|
44
|
+
/**
|
|
45
|
+
* The cached supply resolution, or null until `setSupplyProfile` has
|
|
46
|
+
* resolved once.
|
|
47
|
+
*/
|
|
48
|
+
getSupplyResolution(): SupplyResolution | null;
|
|
49
|
+
/**
|
|
50
|
+
* The last applied supply profile, or null until one has been applied.
|
|
51
|
+
*/
|
|
52
|
+
getSupplyProfile(): SupplyProfile | null;
|
|
53
|
+
prepare(sampleRate: number): void;
|
|
54
|
+
reset(): void;
|
|
55
|
+
getParam(id: string): number | undefined;
|
|
56
|
+
setParam(id: string, value: number): void;
|
|
57
|
+
getParams(): Record<string, number>;
|
|
58
|
+
process(input: Float64Array | Float32Array): Float64Array;
|
|
59
|
+
private resolveSupplies;
|
|
60
|
+
private describeRefusals;
|
|
61
|
+
private compiledVoltsFor;
|
|
62
|
+
private applyProfileToRuntime;
|
|
63
|
+
private fallbackVoltsMagnitude;
|
|
64
|
+
private fallbackOhms;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=runtime-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-node.d.ts","sourceRoot":"","sources":["../../src/nodes/runtime-node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAItE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,kBAAkB,GAAG;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAKF,qBAAa,WAAY,YAAW,SAAS;IAC5C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,qBAAqB;IAClC,QAAQ,UAAS;IACjB,GAAG,SAAO;IAEV,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAA8B;IAE5C,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,WAAW,CAAuB;gBAGzC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,kBAAkB;IAiB7B,UAAU,IAAI,OAAO;IAIrB;;;;;;;;;;;;;;;;;;OAkBG;IACH,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IA0C9C;;;OAGG;IACH,mBAAmB,IAAI,gBAAgB,GAAG,IAAI;IAI9C;;OAEG;IACH,gBAAgB,IAAI,aAAa,GAAG,IAAI;IAIxC,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAWjC,KAAK,IAAI,IAAI;IAYb,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAUxC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAsBzC,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAanC,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,YAAY;IA0BzD,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,qBAAqB;IAuC7B,OAAO,CAAC,sBAAsB;IAkB9B,OAAO,CAAC,YAAY;CASpB"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { resolveSupplyStamps } from "@vessel-dsp/compiler";
|
|
2
|
+
import { ReferenceRuntime } from "@vessel-dsp/runtime";
|
|
3
|
+
import { customSupplyProfile } from "../supply-profile.js";
|
|
4
|
+
const SUPPLY_VOLTS_PARAM = "supplyOpenCircuitVolts";
|
|
5
|
+
const SUPPLY_OHMS_PARAM = "supplyInternalResistanceOhms";
|
|
6
|
+
export class RuntimeNode {
|
|
7
|
+
id;
|
|
8
|
+
name;
|
|
9
|
+
kind = "circuit-runtime";
|
|
10
|
+
bypassed = false;
|
|
11
|
+
mix = 1.0;
|
|
12
|
+
runtime;
|
|
13
|
+
program;
|
|
14
|
+
params = {};
|
|
15
|
+
sampleRate = 48000;
|
|
16
|
+
source;
|
|
17
|
+
supplyResolution = null;
|
|
18
|
+
supplyProfile = null;
|
|
19
|
+
appliedVoltsMagnitude = null;
|
|
20
|
+
appliedOhms = null;
|
|
21
|
+
constructor(id, name, program, options) {
|
|
22
|
+
this.id = id;
|
|
23
|
+
this.name = name;
|
|
24
|
+
this.program = program;
|
|
25
|
+
this.source = options?.source;
|
|
26
|
+
this.runtime = new ReferenceRuntime(program);
|
|
27
|
+
// Initialize default parameters from program controls
|
|
28
|
+
if (program.controls) {
|
|
29
|
+
for (const ctrl of program.controls) {
|
|
30
|
+
this.params[ctrl.id] = ctrl.defaultPosition ?? 0.5;
|
|
31
|
+
this.runtime.setControl(ctrl.id, this.params[ctrl.id]);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
getProgram() {
|
|
36
|
+
return this.program;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Apply a supply profile to the circuit's external supply stamps.
|
|
40
|
+
*
|
|
41
|
+
* Resolves once (lazily, cached) with `resolveSupplyStamps(source,
|
|
42
|
+
* program)`, then retargets every resolved stamp through the runtime's
|
|
43
|
+
* `setSupply`. A null `openCircuitVolts` keeps each stamp's compiled
|
|
44
|
+
* magnitude; an explicit value replaces the magnitude. The sign always
|
|
45
|
+
* follows the stamp's own volts sign read from `getSupplies()`, so a
|
|
46
|
+
* positive-ground germanium rail stays negative.
|
|
47
|
+
*
|
|
48
|
+
* Throws when no source text was given or when nothing resolves, naming
|
|
49
|
+
* the refusal reason codes and rail ids. A program with refused derived
|
|
50
|
+
* rails but one resolved external rail applies to the resolved one and
|
|
51
|
+
* keeps the refusals visible via `getSupplyResolution()`.
|
|
52
|
+
*
|
|
53
|
+
* Callable before and after `prepare()` and between `process()` calls,
|
|
54
|
+
* following the runtime's contract. There is no audio-domain processing
|
|
55
|
+
* in this path.
|
|
56
|
+
*/
|
|
57
|
+
setSupplyProfile(profile) {
|
|
58
|
+
if (profile.openCircuitVolts !== null &&
|
|
59
|
+
(!Number.isFinite(profile.openCircuitVolts) ||
|
|
60
|
+
profile.openCircuitVolts <= 0)) {
|
|
61
|
+
throw new Error(`setSupplyProfile: openCircuitVolts must be null or a finite positive magnitude, got ${String(profile.openCircuitVolts)}`);
|
|
62
|
+
}
|
|
63
|
+
if (!Number.isFinite(profile.internalResistanceOhms) ||
|
|
64
|
+
profile.internalResistanceOhms < 0) {
|
|
65
|
+
throw new Error(`setSupplyProfile: internalResistanceOhms must be a finite non-negative resistance, got ${String(profile.internalResistanceOhms)}`);
|
|
66
|
+
}
|
|
67
|
+
const resolution = this.resolveSupplies();
|
|
68
|
+
if (resolution.supplies.length === 0) {
|
|
69
|
+
throw new Error(`setSupplyProfile: no external supply resolved (${this.describeRefusals(resolution)})`);
|
|
70
|
+
}
|
|
71
|
+
this.applyProfileToRuntime(profile, resolution);
|
|
72
|
+
this.supplyProfile = profile;
|
|
73
|
+
if (profile.openCircuitVolts !== null) {
|
|
74
|
+
this.appliedVoltsMagnitude = profile.openCircuitVolts;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const first = resolution.supplies[0];
|
|
78
|
+
if (first === undefined) {
|
|
79
|
+
throw new Error(`setSupplyProfile: no external supply resolved (${this.describeRefusals(resolution)})`);
|
|
80
|
+
}
|
|
81
|
+
this.appliedVoltsMagnitude = Math.abs(this.compiledVoltsFor(first.address));
|
|
82
|
+
}
|
|
83
|
+
this.appliedOhms = profile.internalResistanceOhms;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The cached supply resolution, or null until `setSupplyProfile` has
|
|
87
|
+
* resolved once.
|
|
88
|
+
*/
|
|
89
|
+
getSupplyResolution() {
|
|
90
|
+
return this.supplyResolution;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The last applied supply profile, or null until one has been applied.
|
|
94
|
+
*/
|
|
95
|
+
getSupplyProfile() {
|
|
96
|
+
return this.supplyProfile;
|
|
97
|
+
}
|
|
98
|
+
prepare(sampleRate) {
|
|
99
|
+
this.sampleRate = sampleRate;
|
|
100
|
+
this.runtime.prepare(sampleRate);
|
|
101
|
+
if (this.supplyProfile !== null && this.supplyResolution !== null) {
|
|
102
|
+
this.applyProfileToRuntime(this.supplyProfile, this.supplyResolution);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
reset() {
|
|
106
|
+
if (this.sampleRate > 0) {
|
|
107
|
+
this.runtime.prepare(this.sampleRate);
|
|
108
|
+
if (this.supplyProfile !== null && this.supplyResolution !== null) {
|
|
109
|
+
this.applyProfileToRuntime(this.supplyProfile, this.supplyResolution);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
getParam(id) {
|
|
114
|
+
if (id === SUPPLY_VOLTS_PARAM) {
|
|
115
|
+
return this.appliedVoltsMagnitude ?? undefined;
|
|
116
|
+
}
|
|
117
|
+
if (id === SUPPLY_OHMS_PARAM) {
|
|
118
|
+
return this.appliedOhms ?? undefined;
|
|
119
|
+
}
|
|
120
|
+
return this.params[id];
|
|
121
|
+
}
|
|
122
|
+
setParam(id, value) {
|
|
123
|
+
if (id === SUPPLY_VOLTS_PARAM || id === SUPPLY_OHMS_PARAM) {
|
|
124
|
+
const currentVolts = this.appliedVoltsMagnitude ?? this.fallbackVoltsMagnitude();
|
|
125
|
+
const currentOhms = this.appliedOhms ?? this.fallbackOhms();
|
|
126
|
+
const nextVolts = id === SUPPLY_VOLTS_PARAM ? value : currentVolts;
|
|
127
|
+
const nextOhms = id === SUPPLY_OHMS_PARAM ? value : currentOhms;
|
|
128
|
+
const custom = customSupplyProfile({
|
|
129
|
+
openCircuitVolts: nextVolts,
|
|
130
|
+
internalResistanceOhms: nextOhms,
|
|
131
|
+
name: "Custom supply (preset)",
|
|
132
|
+
});
|
|
133
|
+
this.setSupplyProfile(custom);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
this.params[id] = value;
|
|
137
|
+
this.runtime.setControl(id, value);
|
|
138
|
+
}
|
|
139
|
+
getParams() {
|
|
140
|
+
const base = { ...this.params };
|
|
141
|
+
if (this.supplyProfile !== null &&
|
|
142
|
+
this.appliedVoltsMagnitude !== null &&
|
|
143
|
+
this.appliedOhms !== null) {
|
|
144
|
+
base[SUPPLY_VOLTS_PARAM] = this.appliedVoltsMagnitude;
|
|
145
|
+
base[SUPPLY_OHMS_PARAM] = this.appliedOhms;
|
|
146
|
+
}
|
|
147
|
+
return base;
|
|
148
|
+
}
|
|
149
|
+
process(input) {
|
|
150
|
+
const length = input.length;
|
|
151
|
+
const input64 = input instanceof Float64Array ? input : new Float64Array(input);
|
|
152
|
+
if (this.bypassed) {
|
|
153
|
+
return new Float64Array(input64);
|
|
154
|
+
}
|
|
155
|
+
const wet = this.runtime.process(input64);
|
|
156
|
+
if (this.mix >= 0.999) {
|
|
157
|
+
return wet;
|
|
158
|
+
}
|
|
159
|
+
const output = new Float64Array(length);
|
|
160
|
+
const wetMix = this.mix;
|
|
161
|
+
const dryMix = 1.0 - wetMix;
|
|
162
|
+
for (let i = 0; i < length; i++) {
|
|
163
|
+
output[i] = dryMix * (input64[i] ?? 0) + wetMix * (wet[i] ?? 0);
|
|
164
|
+
}
|
|
165
|
+
return output;
|
|
166
|
+
}
|
|
167
|
+
resolveSupplies() {
|
|
168
|
+
if (this.supplyResolution !== null) {
|
|
169
|
+
return this.supplyResolution;
|
|
170
|
+
}
|
|
171
|
+
if (this.source === undefined) {
|
|
172
|
+
throw new Error("setSupplyProfile: no source text was given to this RuntimeNode, so no external supply can be resolved: pass the .vdsp text as the fourth constructor argument");
|
|
173
|
+
}
|
|
174
|
+
const resolution = resolveSupplyStamps(this.source, this.program);
|
|
175
|
+
this.supplyResolution = resolution;
|
|
176
|
+
return resolution;
|
|
177
|
+
}
|
|
178
|
+
describeRefusals(resolution) {
|
|
179
|
+
if (resolution.refused.length === 0) {
|
|
180
|
+
return "no refusals recorded";
|
|
181
|
+
}
|
|
182
|
+
return resolution.refused
|
|
183
|
+
.map((entry) => `${entry.reason}(${entry.railComponentId ?? "no-rail"})`)
|
|
184
|
+
.join(", ");
|
|
185
|
+
}
|
|
186
|
+
compiledVoltsFor(address) {
|
|
187
|
+
const block = this.program.blocks[address.blockIndex];
|
|
188
|
+
if (block?.kind !== "mna") {
|
|
189
|
+
throw new Error(`setSupplyProfile: resolved block index ${String(address.blockIndex)} is not an MNA block`);
|
|
190
|
+
}
|
|
191
|
+
for (const stamp of block.stamps) {
|
|
192
|
+
if (stamp.kind === "dc-source" &&
|
|
193
|
+
stamp.sourceIndex === address.sourceIndex) {
|
|
194
|
+
return stamp.volts;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
throw new Error(`setSupplyProfile: resolved supply at block ${String(address.blockIndex)} source ${String(address.sourceIndex)} has no compiled dc-source stamp`);
|
|
198
|
+
}
|
|
199
|
+
applyProfileToRuntime(profile, resolution) {
|
|
200
|
+
const liveByKey = new Map();
|
|
201
|
+
for (const info of this.runtime.getSupplies()) {
|
|
202
|
+
liveByKey.set(`${info.address.blockIndex}:${info.address.sourceIndex}`, info.volts);
|
|
203
|
+
}
|
|
204
|
+
const grouped = new Map();
|
|
205
|
+
for (const supply of resolution.supplies) {
|
|
206
|
+
const compiled = this.compiledVoltsFor(supply.address);
|
|
207
|
+
const live = liveByKey.get(`${supply.address.blockIndex}:${supply.address.sourceIndex}`);
|
|
208
|
+
const signSource = live ?? compiled;
|
|
209
|
+
const sign = signSource < 0 ? -1 : 1;
|
|
210
|
+
const magnitude = profile.openCircuitVolts ?? Math.abs(compiled);
|
|
211
|
+
const targetVolts = sign * magnitude;
|
|
212
|
+
const key = targetVolts;
|
|
213
|
+
let list = grouped.get(key);
|
|
214
|
+
if (list === undefined) {
|
|
215
|
+
list = [];
|
|
216
|
+
grouped.set(key, list);
|
|
217
|
+
}
|
|
218
|
+
list.push(supply.address);
|
|
219
|
+
}
|
|
220
|
+
for (const [targetVolts, addresses] of grouped) {
|
|
221
|
+
this.runtime.setSupply(addresses, targetVolts, profile.internalResistanceOhms);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
fallbackVoltsMagnitude() {
|
|
225
|
+
const live = this.runtime.getSupplies()[0];
|
|
226
|
+
if (live !== undefined && Number.isFinite(live.volts)) {
|
|
227
|
+
const magnitude = Math.abs(live.volts);
|
|
228
|
+
if (magnitude > 0) {
|
|
229
|
+
return magnitude;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (this.supplyResolution !== null) {
|
|
233
|
+
for (const supply of this.supplyResolution.supplies) {
|
|
234
|
+
return Math.abs(this.compiledVoltsFor(supply.address));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
throw new Error("setSupplyProfile: supplyOpenCircuitVolts has no current value to pair with: apply a profile first");
|
|
238
|
+
}
|
|
239
|
+
fallbackOhms() {
|
|
240
|
+
const live = this.runtime.getSupplies()[0];
|
|
241
|
+
if (live !== undefined && Number.isFinite(live.sourceOhms)) {
|
|
242
|
+
return live.sourceOhms;
|
|
243
|
+
}
|
|
244
|
+
throw new Error("setSupplyProfile: supplyInternalResistanceOhms has no current value to pair with: apply a profile first");
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=runtime-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-node.js","sourceRoot":"","sources":["../../src/nodes/runtime-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
export type SupplyProfile = {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
readonly name: string;
|
|
24
|
+
/** Open-circuit EMF magnitude in volts, or null to keep the pedal's own declared supply voltage. */
|
|
25
|
+
readonly openCircuitVolts: number | null;
|
|
26
|
+
/** Series resistance in ohms. */
|
|
27
|
+
readonly internalResistanceOhms: number;
|
|
28
|
+
/** A citation (document, year, table, exact values, how a derived number was computed) or the literal "definition". */
|
|
29
|
+
readonly source: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* The five built-in profiles, and only these. Adapter profiles are
|
|
33
|
+
* deliberately absent: no source was found for a regulated 9 V, regulated
|
|
34
|
+
* 18 V, or unregulated AC/DC resistance or voltage.
|
|
35
|
+
*/
|
|
36
|
+
export declare const SUPPLY_PROFILES: readonly SupplyProfile[];
|
|
37
|
+
/**
|
|
38
|
+
* Build a profile from the caller's own measurement, following Orman's
|
|
39
|
+
* method: read the open-circuit volts E, then the loaded volts across a known
|
|
40
|
+
* resistor Rload, and compute Rint = (Vopen - Vloaded) / (Vloaded / Rload).
|
|
41
|
+
*/
|
|
42
|
+
export declare function profileFromMeasurement(input: {
|
|
43
|
+
readonly openCircuitVolts: number;
|
|
44
|
+
readonly loadedVolts: number;
|
|
45
|
+
readonly loadOhms: number;
|
|
46
|
+
}): SupplyProfile;
|
|
47
|
+
/**
|
|
48
|
+
* Build a profile from caller-supplied numbers (for example a preset
|
|
49
|
+
* round-trip). The source is the caller: no citation is claimed.
|
|
50
|
+
*/
|
|
51
|
+
export declare function customSupplyProfile(input: {
|
|
52
|
+
readonly openCircuitVolts: number | null;
|
|
53
|
+
readonly internalResistanceOhms: number;
|
|
54
|
+
readonly name?: string;
|
|
55
|
+
}): SupplyProfile;
|
|
56
|
+
//# sourceMappingURL=supply-profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supply-profile.d.ts","sourceRoot":"","sources":["../src/supply-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,aAAa,GAAG;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oGAAoG;IACpG,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,iCAAiC;IACjC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,uHAAuH;IACvH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB,CAAC;AA0DF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAMnD,CAAC;AAaF;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC7C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B,GAAG,aAAa,CA8BhB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IAC1C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,aAAa,CAyBhB"}
|