@vessel-dsp/runtime 0.7.0 → 0.12.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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/reference-runtime.d.ts +82 -0
- package/dist/reference-runtime.d.ts.map +1 -1
- package/dist/reference-runtime.js +238 -0
- package/dist/reference-runtime.js.map +1 -1
- package/dist/wasm/v2_dsp.wasm +0 -0
- package/dist/worklet/v2-audio-worklet.js +140 -1
- package/package.json +64 -64
package/dist/wasm/v2_dsp.wasm
CHANGED
|
Binary file
|
|
@@ -1395,6 +1395,42 @@ function ldrTableResistanceOhms(currentsAmps, ohms, currentAmps, minOhms, maxOhm
|
|
|
1395
1395
|
const raw = Math.exp(lnR0 + (lnI - lnI0) * slope);
|
|
1396
1396
|
return Math.min(Math.max(raw, minOhms), maxOhms);
|
|
1397
1397
|
}
|
|
1398
|
+
function dbxVcaGainLinear(gainDb) {
|
|
1399
|
+
return Math.pow(10, gainDb / 20);
|
|
1400
|
+
}
|
|
1401
|
+
function dbxVcaRestTerms(vControl, sustainGain, sustainRef) {
|
|
1402
|
+
return sustainGain * (vControl - sustainRef);
|
|
1403
|
+
}
|
|
1404
|
+
function dbxVcaEnvelopeTerms(inputAmps, slopeVoltsPerNeper, kneeVolts) {
|
|
1405
|
+
const absIn = Math.abs(inputAmps);
|
|
1406
|
+
if (!(absIn > 0)) return 0;
|
|
1407
|
+
return Math.max(0, slopeVoltsPerNeper * Math.log(absIn * 1e6) + kneeVolts);
|
|
1408
|
+
}
|
|
1409
|
+
function dbxVcaKneeVolts(vControl, kneeBaseVolts, kneeTrack) {
|
|
1410
|
+
return kneeBaseVolts + kneeTrack * (vControl - 4.65);
|
|
1411
|
+
}
|
|
1412
|
+
function dbxVcaReleaseTc(depth01, baseSeconds, slowdown) {
|
|
1413
|
+
const depth = Math.min(1, Math.max(0, depth01));
|
|
1414
|
+
return baseSeconds * Math.pow(slowdown, depth);
|
|
1415
|
+
}
|
|
1416
|
+
function dbxVcaPrimeTarget(inputAmps, refCurrentAmps) {
|
|
1417
|
+
return Math.abs(inputAmps) > refCurrentAmps ? 0 : 1;
|
|
1418
|
+
}
|
|
1419
|
+
function dbxVcaShutdownTarget(peakTargetVolts, edgeThreshVolts, primed01, gainPerVolt) {
|
|
1420
|
+
const excess = peakTargetVolts - edgeThreshVolts;
|
|
1421
|
+
if (!(excess > 0) || !(primed01 > 0)) return 0;
|
|
1422
|
+
const primed = Math.min(1, primed01);
|
|
1423
|
+
return gainPerVolt * excess * excess * primed;
|
|
1424
|
+
}
|
|
1425
|
+
function dbxVcaVictimTc(primed01, fastSeconds, slowSeconds) {
|
|
1426
|
+
const primed = Math.min(1, Math.max(0, primed01));
|
|
1427
|
+
return primed > 0.05 ? slowSeconds : fastSeconds;
|
|
1428
|
+
}
|
|
1429
|
+
function dbxVcaEnvelopeK(tcSeconds, sampleRate2) {
|
|
1430
|
+
const denom = tcSeconds * sampleRate2;
|
|
1431
|
+
if (!(denom > 0)) return 1;
|
|
1432
|
+
return 1 - Math.exp(-1 / denom);
|
|
1433
|
+
}
|
|
1398
1434
|
var NEWTON_UNPRODUCTIVE_ITERATIONS = 64;
|
|
1399
1435
|
var NEWTON_UNPRODUCTIVE_PROBATION_SAMPLES = 1024;
|
|
1400
1436
|
var NEWTON_RELATIVE_TOLERANCE = 1e-3;
|
|
@@ -1577,7 +1613,10 @@ var IMPLEMENTED_OPERATORS = {
|
|
|
1577
1613
|
"clock-driver": true,
|
|
1578
1614
|
comparator: true,
|
|
1579
1615
|
// Linear-control VCA cell. Reads the control node, draws nothing.
|
|
1580
|
-
"linear-vca": true
|
|
1616
|
+
"linear-vca": true,
|
|
1617
|
+
// dbx-style VCA cell (uPC1252H2). Bounded sigmoidal gain in the
|
|
1618
|
+
// control voltage. Reads the control node, draws nothing.
|
|
1619
|
+
"dbx-vca": true
|
|
1581
1620
|
};
|
|
1582
1621
|
function unimplementedOperators(required) {
|
|
1583
1622
|
return required.filter(
|
|
@@ -6146,6 +6185,106 @@ var ReferenceRuntime = class {
|
|
|
6146
6185
|
}
|
|
6147
6186
|
break;
|
|
6148
6187
|
}
|
|
6188
|
+
case "dbx-vca": {
|
|
6189
|
+
const dbxBaseIdx = stamp.stateIndex;
|
|
6190
|
+
const ctrlKey = `${block.id}_dbxc_${dbxBaseIdx}`;
|
|
6191
|
+
if (this.elapsedSamples !== (this.lastShiftedSample.get(ctrlKey) ?? -1)) {
|
|
6192
|
+
this.lastShiftedSample.set(ctrlKey, this.elapsedSamples);
|
|
6193
|
+
const vCtrlNow = solution[stamp.control] ?? 0;
|
|
6194
|
+
const ctrlPrev = state[dbxBaseIdx] ?? 0;
|
|
6195
|
+
const ctrlTc = vCtrlNow > ctrlPrev ? stamp.attackSeconds : stamp.releaseSeconds;
|
|
6196
|
+
const ctrlK = dbxVcaEnvelopeK(ctrlTc, this.sampleRate);
|
|
6197
|
+
state[dbxBaseIdx] = ctrlPrev + (vCtrlNow - ctrlPrev) * ctrlK;
|
|
6198
|
+
}
|
|
6199
|
+
const vCtrlHeld = state[dbxBaseIdx] ?? 0;
|
|
6200
|
+
const restHeld = dbxVcaRestTerms(
|
|
6201
|
+
vCtrlHeld,
|
|
6202
|
+
stamp.sustainGain,
|
|
6203
|
+
stamp.sustainRef
|
|
6204
|
+
);
|
|
6205
|
+
const kneeHeld = dbxVcaKneeVolts(
|
|
6206
|
+
vCtrlHeld,
|
|
6207
|
+
stamp.kneeBaseVolts,
|
|
6208
|
+
stamp.kneeTrack
|
|
6209
|
+
);
|
|
6210
|
+
const vInInstDbx = (solution[stamp.plus] ?? 0) - (solution[stamp.minus] ?? 0);
|
|
6211
|
+
const iInInstDbx = vInInstDbx * stamp.inputSiemens;
|
|
6212
|
+
const primeKey = `${block.id}_dbxp_${dbxBaseIdx}`;
|
|
6213
|
+
if (this.elapsedSamples !== (this.lastShiftedSample.get(primeKey) ?? -1)) {
|
|
6214
|
+
this.lastShiftedSample.set(primeKey, this.elapsedSamples);
|
|
6215
|
+
const primeTarget = dbxVcaPrimeTarget(
|
|
6216
|
+
iInInstDbx,
|
|
6217
|
+
stamp.primeRefCurrent
|
|
6218
|
+
);
|
|
6219
|
+
const primePrev = state[dbxBaseIdx + 2] ?? 0;
|
|
6220
|
+
const primeTc = primeTarget > primePrev ? stamp.primeRiseSeconds : stamp.primeFallSeconds;
|
|
6221
|
+
const primeK = dbxVcaEnvelopeK(primeTc, this.sampleRate);
|
|
6222
|
+
state[dbxBaseIdx + 2] = primePrev + (primeTarget - primePrev) * primeK;
|
|
6223
|
+
}
|
|
6224
|
+
const primeHeld = state[dbxBaseIdx + 2] ?? 0;
|
|
6225
|
+
const envKey = `${block.id}_dbxe_${dbxBaseIdx}`;
|
|
6226
|
+
if (this.elapsedSamples !== (this.lastShiftedSample.get(envKey) ?? -1)) {
|
|
6227
|
+
this.lastShiftedSample.set(envKey, this.elapsedSamples);
|
|
6228
|
+
const envTarget = dbxVcaEnvelopeTerms(
|
|
6229
|
+
iInInstDbx,
|
|
6230
|
+
stamp.envelopeSlope,
|
|
6231
|
+
kneeHeld
|
|
6232
|
+
);
|
|
6233
|
+
const envPrev = state[dbxBaseIdx + 1] ?? 0;
|
|
6234
|
+
const envDepth = Math.min(1, Math.max(0, envPrev / 0.15));
|
|
6235
|
+
const envTc = envTarget > envPrev ? stamp.attackSeconds : dbxVcaReleaseTc(envDepth, stamp.releaseSeconds, stamp.releaseSlowdown);
|
|
6236
|
+
const envK = dbxVcaEnvelopeK(envTc, this.sampleRate);
|
|
6237
|
+
state[dbxBaseIdx + 1] = envPrev + (envTarget - envPrev) * envK;
|
|
6238
|
+
}
|
|
6239
|
+
const envHeld = state[dbxBaseIdx + 1] ?? 0;
|
|
6240
|
+
const shutKey = `${block.id}_dbxs_${dbxBaseIdx}`;
|
|
6241
|
+
if (this.elapsedSamples !== (this.lastShiftedSample.get(shutKey) ?? -1)) {
|
|
6242
|
+
this.lastShiftedSample.set(shutKey, this.elapsedSamples);
|
|
6243
|
+
const peakTarget = dbxVcaEnvelopeTerms(
|
|
6244
|
+
iInInstDbx,
|
|
6245
|
+
stamp.envelopeSlope,
|
|
6246
|
+
kneeHeld
|
|
6247
|
+
);
|
|
6248
|
+
const shutTarget = dbxVcaShutdownTarget(
|
|
6249
|
+
peakTarget,
|
|
6250
|
+
stamp.shutdownEdgeVolts,
|
|
6251
|
+
primeHeld,
|
|
6252
|
+
stamp.shutdownGain
|
|
6253
|
+
);
|
|
6254
|
+
const shutPrev = state[dbxBaseIdx + 3] ?? 0;
|
|
6255
|
+
const shutTc = shutTarget > shutPrev ? stamp.shutdownAttackSeconds : dbxVcaVictimTc(
|
|
6256
|
+
primeHeld,
|
|
6257
|
+
stamp.shutdownFastSeconds,
|
|
6258
|
+
stamp.shutdownSlowSeconds
|
|
6259
|
+
);
|
|
6260
|
+
const shutK = dbxVcaEnvelopeK(shutTc, this.sampleRate);
|
|
6261
|
+
state[dbxBaseIdx + 3] = shutPrev + (shutTarget - shutPrev) * shutK;
|
|
6262
|
+
}
|
|
6263
|
+
const shutHeld = state[dbxBaseIdx + 3] ?? 0;
|
|
6264
|
+
const termsHeld = restHeld + envHeld;
|
|
6265
|
+
const rawDb = -termsHeld / 59e-4;
|
|
6266
|
+
const gainDb = Math.min(stamp.maxGainDb, Math.max(stamp.minGainDb, rawDb));
|
|
6267
|
+
const totalDb = Math.max(-100, gainDb - shutHeld / 59e-4);
|
|
6268
|
+
const gain = dbxVcaGainLinear(totalDb);
|
|
6269
|
+
const vPlus = solution[stamp.plus] ?? 0;
|
|
6270
|
+
const vMinus = solution[stamp.minus] ?? 0;
|
|
6271
|
+
const vIn = vPlus - vMinus;
|
|
6272
|
+
const iIn = vIn * stamp.inputSiemens;
|
|
6273
|
+
const iOut = iIn * gain;
|
|
6274
|
+
const gIn = gain * stamp.inputSiemens;
|
|
6275
|
+
const leaving = -iOut;
|
|
6276
|
+
const equivalent = leaving - (-gIn * vPlus + gIn * vMinus);
|
|
6277
|
+
if (stamp.output !== 0) {
|
|
6278
|
+
if (stamp.plus !== 0) {
|
|
6279
|
+
matrix[stamp.output][stamp.plus] += -gIn;
|
|
6280
|
+
}
|
|
6281
|
+
if (stamp.minus !== 0) {
|
|
6282
|
+
matrix[stamp.output][stamp.minus] += gIn;
|
|
6283
|
+
}
|
|
6284
|
+
rhs[stamp.output] = (rhs[stamp.output] ?? 0) - equivalent;
|
|
6285
|
+
}
|
|
6286
|
+
break;
|
|
6287
|
+
}
|
|
6149
6288
|
case "spring-reverb": {
|
|
6150
6289
|
const conductance = 1 / Math.max(stamp.inputOhms, MIN_STAMP_OHMS);
|
|
6151
6290
|
matrix[stamp.inputPlus][stamp.inputPlus] += conductance;
|
package/package.json
CHANGED
|
@@ -1,66 +1,66 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
2
|
+
"name": "@vessel-dsp/runtime",
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"description": "Real-time MNA simulation runtime and solver console for VesselDSP Program ROMs.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"guitar-pedal",
|
|
7
|
+
"electronics",
|
|
8
|
+
"simulation",
|
|
9
|
+
"dsp",
|
|
10
|
+
"runtime",
|
|
11
|
+
"solver",
|
|
12
|
+
"mna"
|
|
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
|
+
"./package.json": {
|
|
32
|
+
"default": "./package.json"
|
|
33
|
+
},
|
|
34
|
+
"./wasm/*": {
|
|
35
|
+
"default": "./dist/wasm/*"
|
|
36
|
+
},
|
|
37
|
+
"./worklet.js": {
|
|
38
|
+
"default": "./dist/worklet/v2-audio-worklet.js"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"main": "./dist/index.js",
|
|
42
|
+
"module": "./dist/index.js",
|
|
43
|
+
"types": "./dist/index.d.ts",
|
|
44
|
+
"files": [
|
|
45
|
+
"dist",
|
|
46
|
+
"README.md",
|
|
47
|
+
"LICENSE.md"
|
|
48
|
+
],
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsc -p tsconfig.build.json && bun run ../../scripts/fix-dist-imports.ts dist && rm -rf dist/wasm && cp -r src/wasm dist/wasm && bun scripts/build-worklet.ts",
|
|
51
|
+
"clean": "rm -rf dist",
|
|
52
|
+
"prepack": "bun run --cwd ../core build && bun run --cwd ../compiler build && bun run build:wasm && bun run build",
|
|
53
|
+
"pack:dry-run": "npm pack --dry-run",
|
|
54
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
55
|
+
"build:wasm": "bash scripts/build-wasm.sh",
|
|
56
|
+
"build:worklet": "bun scripts/build-worklet.ts",
|
|
57
|
+
"test": "bun test tests",
|
|
58
|
+
"generate-kernels": "bun scripts/generate-kernels.ts"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@vessel-dsp/compiler": "0.14.0"
|
|
62
|
+
},
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
}
|
|
66
66
|
}
|