@vessel-dsp/runtime 0.6.3 → 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 +93 -0
- package/dist/reference-runtime.d.ts.map +1 -1
- package/dist/reference-runtime.js +307 -13
- package/dist/reference-runtime.js.map +1 -1
- package/dist/wasm/v2_dsp.wasm +0 -0
- package/dist/worklet/v2-audio-worklet.js +184 -2
- package/package.json +64 -64
package/dist/wasm/v2_dsp.wasm
CHANGED
|
Binary file
|
|
@@ -1360,6 +1360,77 @@ function reverbCombGain(delaySeconds, decaySeconds) {
|
|
|
1360
1360
|
return Math.min(0.999, 10 ** (-3 * delaySeconds / decaySeconds));
|
|
1361
1361
|
}
|
|
1362
1362
|
var DEFAULT_NEWTON_MAX_ITERATIONS = 1024;
|
|
1363
|
+
function ldrTableResistanceOhms(currentsAmps, ohms, currentAmps, minOhms, maxOhms) {
|
|
1364
|
+
if (!(currentAmps > 0)) {
|
|
1365
|
+
return maxOhms;
|
|
1366
|
+
}
|
|
1367
|
+
const n = currentsAmps.length;
|
|
1368
|
+
let lo = 0;
|
|
1369
|
+
let hi = 1;
|
|
1370
|
+
if (currentAmps <= currentsAmps[0]) {
|
|
1371
|
+
lo = 0;
|
|
1372
|
+
hi = 1;
|
|
1373
|
+
} else if (currentAmps >= currentsAmps[n - 1]) {
|
|
1374
|
+
lo = n - 2;
|
|
1375
|
+
hi = n - 1;
|
|
1376
|
+
} else {
|
|
1377
|
+
for (let i = 0; i < n - 1; i++) {
|
|
1378
|
+
if (currentAmps >= currentsAmps[i] && currentAmps <= currentsAmps[i + 1]) {
|
|
1379
|
+
lo = i;
|
|
1380
|
+
hi = i + 1;
|
|
1381
|
+
break;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
const iA = currentsAmps[lo];
|
|
1386
|
+
const iB = currentsAmps[hi];
|
|
1387
|
+
const rA = ohms[lo];
|
|
1388
|
+
const rB = ohms[hi];
|
|
1389
|
+
const lnI = Math.log(currentAmps);
|
|
1390
|
+
const lnI0 = Math.log(iA);
|
|
1391
|
+
const lnI1 = Math.log(iB);
|
|
1392
|
+
const lnR0 = Math.log(rA);
|
|
1393
|
+
const lnR1 = Math.log(rB);
|
|
1394
|
+
const slope = (lnR1 - lnR0) / (lnI1 - lnI0);
|
|
1395
|
+
const raw = Math.exp(lnR0 + (lnI - lnI0) * slope);
|
|
1396
|
+
return Math.min(Math.max(raw, minOhms), maxOhms);
|
|
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
|
+
}
|
|
1363
1434
|
var NEWTON_UNPRODUCTIVE_ITERATIONS = 64;
|
|
1364
1435
|
var NEWTON_UNPRODUCTIVE_PROBATION_SAMPLES = 1024;
|
|
1365
1436
|
var NEWTON_RELATIVE_TOLERANCE = 1e-3;
|
|
@@ -1542,7 +1613,10 @@ var IMPLEMENTED_OPERATORS = {
|
|
|
1542
1613
|
"clock-driver": true,
|
|
1543
1614
|
comparator: true,
|
|
1544
1615
|
// Linear-control VCA cell. Reads the control node, draws nothing.
|
|
1545
|
-
"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
|
|
1546
1620
|
};
|
|
1547
1621
|
function unimplementedOperators(required) {
|
|
1548
1622
|
return required.filter(
|
|
@@ -5376,7 +5450,15 @@ var ReferenceRuntime = class {
|
|
|
5376
5450
|
rhs[stamp.ledCathode] = (rhs[stamp.ledCathode] ?? 0) + ledEquivalent;
|
|
5377
5451
|
const alpha = 1e3;
|
|
5378
5452
|
let rLdr;
|
|
5379
|
-
if (stamp.
|
|
5453
|
+
if (stamp.ldrTableCurrentAmps !== void 0 && stamp.ldrTableOhms !== void 0 && stamp.ldrTableCurrentAmps.length === stamp.ldrTableOhms.length && stamp.ldrTableCurrentAmps.length >= 2) {
|
|
5454
|
+
rLdr = ldrTableResistanceOhms(
|
|
5455
|
+
stamp.ldrTableCurrentAmps,
|
|
5456
|
+
stamp.ldrTableOhms,
|
|
5457
|
+
ledCurrent,
|
|
5458
|
+
stamp.ldrMinOhms,
|
|
5459
|
+
stamp.ldrMaxOhms
|
|
5460
|
+
);
|
|
5461
|
+
} else if (stamp.ldrPowerLawCoefficientOhms !== void 0 && stamp.ldrPowerLawExponent !== void 0) {
|
|
5380
5462
|
const powerLawCurrent = Math.max(ledCurrent, 0);
|
|
5381
5463
|
const raw = stamp.ldrPowerLawCoefficientOhms * Math.pow(powerLawCurrent, stamp.ldrPowerLawExponent);
|
|
5382
5464
|
rLdr = Math.min(Math.max(raw, stamp.ldrMinOhms), stamp.ldrMaxOhms);
|
|
@@ -6103,6 +6185,106 @@ var ReferenceRuntime = class {
|
|
|
6103
6185
|
}
|
|
6104
6186
|
break;
|
|
6105
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
|
+
}
|
|
6106
6288
|
case "spring-reverb": {
|
|
6107
6289
|
const conductance = 1 / Math.max(stamp.inputOhms, MIN_STAMP_OHMS);
|
|
6108
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
|
}
|