@opendaw/studio-core-wasm 0.0.7 → 0.0.8
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/WasmEngine.d.ts.map +1 -1
- package/dist/WasmEngine.js +7 -50
- package/dist/analysis-dsp.d.ts +16 -0
- package/dist/analysis-dsp.d.ts.map +1 -0
- package/dist/analysis-dsp.js +198 -0
- package/dist/device-linker.d.ts +3 -1
- package/dist/device-linker.d.ts.map +1 -1
- package/dist/device-linker.js +1 -1
- package/dist/engine-exports.d.ts +1 -1
- package/dist/engine-exports.d.ts.map +1 -1
- package/dist/engine-modules.d.ts +2 -0
- package/dist/engine-modules.d.ts.map +1 -1
- package/dist/engine-modules.js +12 -24
- package/dist/protocol.d.ts +0 -8
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +0 -1
- package/dist/wasm/engine.wasm +0 -0
- package/dist/wasm/plugins/device_apparat.wasm +0 -0
- package/dist/wasm/plugins/device_arpeggio.wasm +0 -0
- package/dist/wasm/plugins/device_autotune.wasm +0 -0
- package/dist/wasm/plugins/device_compressor.wasm +0 -0
- package/dist/wasm/plugins/device_crusher.wasm +0 -0
- package/dist/wasm/plugins/device_dattorro_reverb.wasm +0 -0
- package/dist/wasm/plugins/device_delay.wasm +0 -0
- package/dist/wasm/plugins/device_fold.wasm +0 -0
- package/dist/wasm/plugins/device_gate.wasm +0 -0
- package/dist/wasm/plugins/device_maximizer.wasm +0 -0
- package/dist/wasm/plugins/device_nano.wasm +0 -0
- package/dist/wasm/plugins/device_neural_amp.wasm +0 -0
- package/dist/wasm/plugins/device_pitch.wasm +0 -0
- package/dist/wasm/plugins/device_playfield_sample.wasm +0 -0
- package/dist/wasm/plugins/device_revamp.wasm +0 -0
- package/dist/wasm/plugins/device_reverb.wasm +0 -0
- package/dist/wasm/plugins/device_soundfont.wasm +0 -0
- package/dist/wasm/plugins/device_spielwerk.wasm +0 -0
- package/dist/wasm/plugins/device_stereo_tool.wasm +0 -0
- package/dist/wasm/plugins/device_tidal.wasm +0 -0
- package/dist/wasm/plugins/device_vaporisateur.wasm +0 -0
- package/dist/wasm/plugins/device_velocity.wasm +0 -0
- package/dist/wasm/plugins/device_vocoder.wasm +0 -0
- package/dist/wasm/plugins/device_waveshaper.wasm +0 -0
- package/dist/wasm/plugins/device_werkstatt.wasm +0 -0
- package/dist/wasm/plugins/device_zeitgeist.wasm +0 -0
- package/dist/wasm-offline-worker.js +10 -10
- package/dist/wasm-offline-worker.js.map +3 -3
- package/dist/wasm-processor.js +30 -30
- package/dist/wasm-processor.js.map +4 -4
- package/package.json +6 -6
package/dist/WasmEngine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasmEngine.d.ts","sourceRoot":"","sources":["../src/WasmEngine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WasmEngine.d.ts","sourceRoot":"","sources":["../src/WasmEngine.ts"],"names":[],"mappings":"AAoBA,MAAM,MAAM,cAAc,GAAG;IAEzB,YAAY,EAAE,MAAM,CAAA;IAEpB,gBAAgB,EAAE,MAAM,CAAA;IAExB,OAAO,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,yBAAiB,UAAU,CAAC;IAKjB,MAAM,OAAO,QAAO,OAA6B,CAAA;IAKjD,MAAM,WAAW,GAAU,SAAS,gBAAgB,KAAG,OAAO,CAAC,OAAO,CAa5E,CAAA;IAEM,MAAM,OAAO,GAAI,MAAM,cAAc,KAAG,IAkB9C,CAAA;CA6CJ"}
|
package/dist/WasmEngine.js
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
// construction, and wires the offline render variant. `ensureReady` compiles the modules + registers the
|
|
5
5
|
// processor module once. The WASM engine is the DEFAULT; localStorage only records an explicit opt-out.
|
|
6
6
|
// Every engine (re)boot re-reads it, so the existing restart machinery swaps engines without a page reload.
|
|
7
|
-
import {
|
|
7
|
+
import { MutableObservableOption } from "@opendaw/lib-std";
|
|
8
8
|
import { Communicator, Promises } from "@opendaw/lib-runtime";
|
|
9
9
|
import { SyncSource } from "@opendaw/lib-box";
|
|
10
10
|
import { EngineVariant, OfflineEngineRenderer } from "@opendaw/studio-core";
|
|
11
|
-
import {
|
|
11
|
+
import { loadEngineModules } from "./engine-modules";
|
|
12
12
|
import { serializeUpdateTasks } from "./sync/serialize-update-tasks";
|
|
13
13
|
import { createSyncLoopback } from "./sync/loopback";
|
|
14
|
-
import { WASM_ENGINE_PROCESSOR_NAME,
|
|
14
|
+
import { WASM_ENGINE_PROCESSOR_NAME, WASM_SYNC_CHANNEL } from "./protocol";
|
|
15
15
|
export var WasmEngine;
|
|
16
16
|
(function (WasmEngine) {
|
|
17
17
|
const modules = new MutableObservableOption();
|
|
@@ -44,59 +44,16 @@ export var WasmEngine;
|
|
|
44
44
|
OfflineEngineRenderer.install(urls.offlineWorkerUrl, { wasmUrl: urls.wasmUrl });
|
|
45
45
|
EngineVariant.install(() => {
|
|
46
46
|
const { engineModule, deviceModules, deviceBoxTypes, composites, effectComposites } = modules.unwrap("WasmEngine.ensureReady must succeed before an engine boots");
|
|
47
|
-
const attachment = {
|
|
48
|
-
// A FRESH shared memory per boot: re-instantiating the engine re-applies its data segments,
|
|
49
|
-
// but a recycled heap would leak every allocation of the previous engine instance.
|
|
50
|
-
engineModule, deviceModules, deviceBoxTypes, composites, effectComposites,
|
|
51
|
-
memory: createEngineMemory()
|
|
52
|
-
};
|
|
47
|
+
const attachment = { engineModule, deviceModules, deviceBoxTypes, composites, effectComposites };
|
|
53
48
|
return {
|
|
54
49
|
processorName: WASM_ENGINE_PROCESSOR_NAME,
|
|
55
50
|
attachment,
|
|
56
|
-
connectSync: (messenger, project) => connectSync(messenger, project)
|
|
57
|
-
connectFrozenAudio:
|
|
51
|
+
connectSync: (messenger, project) => connectSync(messenger, project)
|
|
52
|
+
// No connectFrozenAudio: the memory is worklet-owned (non-shared), so frozen PCM travels
|
|
53
|
+
// through the `setFrozenAudio` engine command and is copied worklet-side.
|
|
58
54
|
};
|
|
59
55
|
});
|
|
60
56
|
};
|
|
61
|
-
// Freeze PCM delivery: the worklet only ALLOCATES (a small RPC returning the engine's planar stereo
|
|
62
|
-
// pointer) and ATTACHES — the bulk copy runs here on the MAIN thread, straight into the shared engine
|
|
63
|
-
// memory. Operations chain sequentially: a second freeze reallocates `frozen_pending`, so no write may
|
|
64
|
-
// start while another is between allocate and attach (the engine reboot replay sends several at once).
|
|
65
|
-
// The worklet may memory.grow inside `frozen_allocate`, which leaves previously obtained buffer
|
|
66
|
-
// references stale (they keep their pre-grow length), so the buffer is re-read after the RPC returns.
|
|
67
|
-
const connectFrozenAudio = (messenger, memory) => {
|
|
68
|
-
const sender = Communicator.sender(messenger.channel(WASM_FROZEN_CHANNEL), dispatcher => new class {
|
|
69
|
-
frozenAllocate(frameCount, channels) {
|
|
70
|
-
return dispatcher.dispatchAndReturn(this.frozenAllocate, frameCount, channels);
|
|
71
|
-
}
|
|
72
|
-
frozenAttach(uuid, frameCount, channels, sampleRate) {
|
|
73
|
-
dispatcher.dispatchAndForget(this.frozenAttach, uuid, frameCount, channels, sampleRate);
|
|
74
|
-
}
|
|
75
|
-
frozenClear(uuid) { dispatcher.dispatchAndForget(this.frozenClear, uuid); }
|
|
76
|
-
});
|
|
77
|
-
const queue = { tail: Promise.resolve() };
|
|
78
|
-
return (uuid, audioData) => {
|
|
79
|
-
queue.tail = queue.tail.then(() => {
|
|
80
|
-
if (isNull(audioData)) {
|
|
81
|
-
sender.frozenClear(uuid);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const { frames, numberOfFrames, numberOfChannels, sampleRate } = audioData;
|
|
85
|
-
const channels = Math.min(numberOfChannels, 2);
|
|
86
|
-
return sender.frozenAllocate(numberOfFrames, channels).then(pointer => {
|
|
87
|
-
if (pointer === 0) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const buffer = memory.buffer;
|
|
91
|
-
for (let channel = 0; channel < channels; channel++) {
|
|
92
|
-
new Float32Array(buffer, pointer + channel * numberOfFrames * Float32Array.BYTES_PER_ELEMENT, numberOfFrames)
|
|
93
|
-
.set(frames[channel]);
|
|
94
|
-
}
|
|
95
|
-
sender.frozenAttach(uuid, numberOfFrames, channels, sampleRate);
|
|
96
|
-
});
|
|
97
|
-
}).catch(reason => console.warn("frozen audio delivery failed:", reason));
|
|
98
|
-
};
|
|
99
|
-
};
|
|
100
57
|
// SyncSource (unchanged) -> SYNCHRONOUS loopback -> serialize at emission time (the source graph's
|
|
101
58
|
// schema AND state — a MessageChannel hop would let a later transaction delete boxes before the batch
|
|
102
59
|
// resolves its primitive codecs) -> transaction bytes to the worklet's apply_updates. The `true` flag
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class StereoAnalyser {
|
|
2
|
+
#private;
|
|
3
|
+
process(left: Float32Array, right: Float32Array, out: Float32Array): void;
|
|
4
|
+
}
|
|
5
|
+
export declare class GonioCapture {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(pairs: number);
|
|
8
|
+
process(left: Float32Array, right: Float32Array, out: Float32Array): void;
|
|
9
|
+
}
|
|
10
|
+
export declare class LoudnessMeter {
|
|
11
|
+
#private;
|
|
12
|
+
constructor(sampleRate: number);
|
|
13
|
+
process(left: Float32Array, right: Float32Array): void;
|
|
14
|
+
fill(out: Float32Array): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=analysis-dsp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysis-dsp.d.ts","sourceRoot":"","sources":["../src/analysis-dsp.ts"],"names":[],"mappings":"AAMA,qBAAa,cAAc;;IAKvB,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI;CA8B5E;AAGD,qBAAa,YAAY;;gBAKT,KAAK,EAAE,MAAM;IAEzB,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI;CAS5E;AAKD,qBAAa,aAAa;;gBA0BV,UAAU,EAAE,MAAM;IAQ9B,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI;IAkBtD,IAAI,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI;CAyFhC"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// Extra Analysis-panel measurements computed on the realtime master output: stereo correlation/width,
|
|
2
|
+
// goniometer sample capture, and EBU R128 / ITU-R BS.1770 loudness. Each is only stepped by the
|
|
3
|
+
// processor while its broadcast has subscribers (i.e. the panel/card is visible).
|
|
4
|
+
import { BiquadCoeff, BiquadMono } from "@opendaw/lib-dsp";
|
|
5
|
+
export class StereoAnalyser {
|
|
6
|
+
#corr = 0.0;
|
|
7
|
+
#width = 0.0;
|
|
8
|
+
#balance = 0.0;
|
|
9
|
+
process(left, right, out) {
|
|
10
|
+
const n = left.length;
|
|
11
|
+
let sumLR = 0.0;
|
|
12
|
+
let sumLL = 0.0;
|
|
13
|
+
let sumRR = 0.0;
|
|
14
|
+
let sumMid = 0.0;
|
|
15
|
+
let sumSide = 0.0;
|
|
16
|
+
for (let i = 0; i < n; i++) {
|
|
17
|
+
const l = left[i];
|
|
18
|
+
const r = right[i];
|
|
19
|
+
sumLR += l * r;
|
|
20
|
+
sumLL += l * l;
|
|
21
|
+
sumRR += r * r;
|
|
22
|
+
const mid = (l + r) * 0.5;
|
|
23
|
+
const side = (l - r) * 0.5;
|
|
24
|
+
sumMid += mid * mid;
|
|
25
|
+
sumSide += side * side;
|
|
26
|
+
}
|
|
27
|
+
const corr = sumLL > 1e-12 && sumRR > 1e-12 ? sumLR / Math.sqrt(sumLL * sumRR) : 0.0;
|
|
28
|
+
const width = sumMid + sumSide > 1e-12 ? sumSide / (sumMid + sumSide) : 0.0;
|
|
29
|
+
const balance = sumLL + sumRR > 1e-12 ? (sumRR - sumLL) / (sumLL + sumRR) : 0.0;
|
|
30
|
+
this.#corr += (corr - this.#corr) * 0.1;
|
|
31
|
+
this.#width += (width - this.#width) * 0.1;
|
|
32
|
+
this.#balance += (balance - this.#balance) * 0.1;
|
|
33
|
+
out[0] = this.#corr;
|
|
34
|
+
out[1] = this.#width;
|
|
35
|
+
out[2] = this.#balance;
|
|
36
|
+
out[3] = Math.sqrt(sumMid / Math.max(1, n));
|
|
37
|
+
out[4] = Math.sqrt(sumSide / Math.max(1, n));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Interleaved L/R ring for the goniometer. `out` length is PAIRS * 2.
|
|
41
|
+
export class GonioCapture {
|
|
42
|
+
#pairs;
|
|
43
|
+
#write = 0;
|
|
44
|
+
constructor(pairs) { this.#pairs = pairs; }
|
|
45
|
+
process(left, right, out) {
|
|
46
|
+
const n = left.length;
|
|
47
|
+
for (let i = 0; i < n; i++) {
|
|
48
|
+
const base = this.#write * 2;
|
|
49
|
+
out[base] = left[i];
|
|
50
|
+
out[base + 1] = right[i];
|
|
51
|
+
this.#write = (this.#write + 1) % this.#pairs;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// ITU-R BS.1770-4 loudness: momentary (400 ms), short-term (3 s), gated integrated, and EBU R128
|
|
56
|
+
// loudness range. Values are LUFS (LU for LRA); truePeak is dBTP (4x oversampled). Approximated on
|
|
57
|
+
// 100 ms non-overlapping blocks.
|
|
58
|
+
export class LoudnessMeter {
|
|
59
|
+
static #ABSOLUTE_GATE = -70.0;
|
|
60
|
+
static #HIST_MIN = -70.0;
|
|
61
|
+
static #HIST_STEP = 0.1;
|
|
62
|
+
static #HIST_BINS = 800; // -70 .. +10 LUFS
|
|
63
|
+
#shelfCoeff = new BiquadCoeff();
|
|
64
|
+
#hpCoeff = new BiquadCoeff();
|
|
65
|
+
#shelfL = new BiquadMono();
|
|
66
|
+
#shelfR = new BiquadMono();
|
|
67
|
+
#hpL = new BiquadMono();
|
|
68
|
+
#hpR = new BiquadMono();
|
|
69
|
+
#momentaryMs; // ring of 100 ms block mean-squares
|
|
70
|
+
#shortMs;
|
|
71
|
+
#integHist = new Float32Array(LoudnessMeter.#HIST_BINS);
|
|
72
|
+
#shortHist = new Float32Array(LoudnessMeter.#HIST_BINS);
|
|
73
|
+
#blockSamples;
|
|
74
|
+
#momentaryWrite = 0;
|
|
75
|
+
#shortWrite = 0;
|
|
76
|
+
#accum = 0.0;
|
|
77
|
+
#accumCount = 0;
|
|
78
|
+
#truePeak = 0.0;
|
|
79
|
+
constructor(sampleRate) {
|
|
80
|
+
this.#shelfCoeff.setHighShelfParams(1681.974450955533 / sampleRate, 3.999843853973347);
|
|
81
|
+
this.#hpCoeff.setHighpassParams(38.13547087602444 / sampleRate, 0.5003270373238773);
|
|
82
|
+
this.#blockSamples = Math.max(1, Math.round(sampleRate * 0.1));
|
|
83
|
+
this.#momentaryMs = new Float32Array(4);
|
|
84
|
+
this.#shortMs = new Float32Array(30);
|
|
85
|
+
}
|
|
86
|
+
process(left, right) {
|
|
87
|
+
const n = left.length;
|
|
88
|
+
for (let i = 0; i < n; i++) {
|
|
89
|
+
const l = left[i];
|
|
90
|
+
const r = right[i];
|
|
91
|
+
const kl = this.#hpL.processFrame(this.#hpCoeff, this.#shelfL.processFrame(this.#shelfCoeff, l));
|
|
92
|
+
const kr = this.#hpR.processFrame(this.#hpCoeff, this.#shelfR.processFrame(this.#shelfCoeff, r));
|
|
93
|
+
this.#accum += kl * kl + kr * kr;
|
|
94
|
+
const peak = Math.max(Math.abs(l), Math.abs(r));
|
|
95
|
+
if (peak > this.#truePeak) {
|
|
96
|
+
this.#truePeak = peak;
|
|
97
|
+
}
|
|
98
|
+
if (++this.#accumCount >= this.#blockSamples) {
|
|
99
|
+
this.#pushBlock(this.#accum / this.#accumCount);
|
|
100
|
+
this.#accum = 0.0;
|
|
101
|
+
this.#accumCount = 0;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
fill(out) {
|
|
106
|
+
out[0] = LoudnessMeter.#loudnessOf(LoudnessMeter.#mean(this.#momentaryMs));
|
|
107
|
+
out[1] = LoudnessMeter.#loudnessOf(LoudnessMeter.#mean(this.#shortMs));
|
|
108
|
+
out[2] = this.#integrated();
|
|
109
|
+
out[3] = this.#loudnessRange();
|
|
110
|
+
out[4] = this.#truePeak > 1e-7 ? 20.0 * Math.log10(this.#truePeak) : -120.0;
|
|
111
|
+
}
|
|
112
|
+
#pushBlock(meanSquare) {
|
|
113
|
+
this.#momentaryMs[this.#momentaryWrite] = meanSquare;
|
|
114
|
+
this.#momentaryWrite = (this.#momentaryWrite + 1) % this.#momentaryMs.length;
|
|
115
|
+
this.#shortMs[this.#shortWrite] = meanSquare;
|
|
116
|
+
this.#shortWrite = (this.#shortWrite + 1) % this.#shortMs.length;
|
|
117
|
+
const blockLoudness = LoudnessMeter.#loudnessOf(meanSquare);
|
|
118
|
+
if (blockLoudness >= LoudnessMeter.#ABSOLUTE_GATE) {
|
|
119
|
+
LoudnessMeter.#addToHist(this.#integHist, blockLoudness);
|
|
120
|
+
}
|
|
121
|
+
const shortLoudness = LoudnessMeter.#loudnessOf(LoudnessMeter.#mean(this.#shortMs));
|
|
122
|
+
if (shortLoudness >= LoudnessMeter.#ABSOLUTE_GATE) {
|
|
123
|
+
LoudnessMeter.#addToHist(this.#shortHist, shortLoudness);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
#integrated() {
|
|
127
|
+
const absMean = LoudnessMeter.#histEnergyMean(this.#integHist, LoudnessMeter.#ABSOLUTE_GATE);
|
|
128
|
+
if (absMean <= 0.0) {
|
|
129
|
+
return -120.0;
|
|
130
|
+
}
|
|
131
|
+
const relThreshold = LoudnessMeter.#loudnessOf(absMean) - 10.0;
|
|
132
|
+
const relMean = LoudnessMeter.#histEnergyMean(this.#integHist, relThreshold);
|
|
133
|
+
return relMean > 0.0 ? LoudnessMeter.#loudnessOf(relMean) : -120.0;
|
|
134
|
+
}
|
|
135
|
+
#loudnessRange() {
|
|
136
|
+
const absMean = LoudnessMeter.#histEnergyMean(this.#shortHist, LoudnessMeter.#ABSOLUTE_GATE);
|
|
137
|
+
if (absMean <= 0.0) {
|
|
138
|
+
return 0.0;
|
|
139
|
+
}
|
|
140
|
+
const relThreshold = LoudnessMeter.#loudnessOf(absMean) - 20.0;
|
|
141
|
+
const low = LoudnessMeter.#histPercentile(this.#shortHist, relThreshold, 0.1);
|
|
142
|
+
const high = LoudnessMeter.#histPercentile(this.#shortHist, relThreshold, 0.95);
|
|
143
|
+
return Math.max(0.0, high - low);
|
|
144
|
+
}
|
|
145
|
+
static #mean(values) {
|
|
146
|
+
let sum = 0.0;
|
|
147
|
+
for (let i = 0; i < values.length; i++) {
|
|
148
|
+
sum += values[i];
|
|
149
|
+
}
|
|
150
|
+
return sum / values.length;
|
|
151
|
+
}
|
|
152
|
+
static #loudnessOf(meanSquare) {
|
|
153
|
+
return meanSquare > 1e-12 ? -0.691 + 10.0 * Math.log10(meanSquare) : -120.0;
|
|
154
|
+
}
|
|
155
|
+
static #binOf(loudness) {
|
|
156
|
+
const index = Math.floor((loudness - LoudnessMeter.#HIST_MIN) / LoudnessMeter.#HIST_STEP);
|
|
157
|
+
return Math.max(0, Math.min(LoudnessMeter.#HIST_BINS - 1, index));
|
|
158
|
+
}
|
|
159
|
+
static #loudnessAtBin(index) {
|
|
160
|
+
return LoudnessMeter.#HIST_MIN + (index + 0.5) * LoudnessMeter.#HIST_STEP;
|
|
161
|
+
}
|
|
162
|
+
static #addToHist(hist, loudness) {
|
|
163
|
+
hist[LoudnessMeter.#binOf(loudness)] += 1.0;
|
|
164
|
+
}
|
|
165
|
+
static #histEnergyMean(hist, threshold) {
|
|
166
|
+
let energy = 0.0;
|
|
167
|
+
let count = 0.0;
|
|
168
|
+
const from = LoudnessMeter.#binOf(threshold);
|
|
169
|
+
for (let i = from; i < LoudnessMeter.#HIST_BINS; i++) {
|
|
170
|
+
const c = hist[i];
|
|
171
|
+
if (c <= 0.0) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
energy += c * Math.pow(10.0, (LoudnessMeter.#loudnessAtBin(i) + 0.691) / 10.0);
|
|
175
|
+
count += c;
|
|
176
|
+
}
|
|
177
|
+
return count > 0.0 ? energy / count : 0.0;
|
|
178
|
+
}
|
|
179
|
+
static #histPercentile(hist, threshold, fraction) {
|
|
180
|
+
const from = LoudnessMeter.#binOf(threshold);
|
|
181
|
+
let total = 0.0;
|
|
182
|
+
for (let i = from; i < LoudnessMeter.#HIST_BINS; i++) {
|
|
183
|
+
total += hist[i];
|
|
184
|
+
}
|
|
185
|
+
if (total <= 0.0) {
|
|
186
|
+
return LoudnessMeter.#HIST_MIN;
|
|
187
|
+
}
|
|
188
|
+
const target = total * fraction;
|
|
189
|
+
let running = 0.0;
|
|
190
|
+
for (let i = from; i < LoudnessMeter.#HIST_BINS; i++) {
|
|
191
|
+
running += hist[i];
|
|
192
|
+
if (running >= target) {
|
|
193
|
+
return LoudnessMeter.#loudnessAtBin(i);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return LoudnessMeter.#loudnessAtBin(LoudnessMeter.#HIST_BINS - 1);
|
|
197
|
+
}
|
|
198
|
+
}
|
package/dist/device-linker.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export type LinkerEngine = {
|
|
|
24
24
|
device_alloc: (size: number) => number;
|
|
25
25
|
device_register: (processIndex: number, stateSize: number, kind: number, initIndex: number, parameterChangedIndex: number, fieldChangedIndex: number, sampleChangedIndex: number, soundfontChangedIndex: number, resetIndex: number, terminateIndex: number, midiEffectsField: number, audioEffectsField: number, paramCollectionField: number, sampleCollectionField: number) => number;
|
|
26
26
|
device_set_box_type: (deviceId: number, nameLen: number) => void;
|
|
27
|
-
composite_register: (nameLen: number, childrenField: number, indexKey: number, excludeKey: number, cellInstrumentField: number, cellMidiField: number, cellAudioField: number, childEnabledKey: number, childMuteKey: number, childSoloKey: number) => void;
|
|
27
|
+
composite_register: (nameLen: number, childrenField: number, indexKey: number, excludeKey: number, cellInstrumentField: number, cellMidiField: number, cellAudioField: number, childEnabledKey: number, childMuteKey: number, childSoloKey: number, childVolumeKey: number, childPanKey: number) => void;
|
|
28
28
|
effect_composite_register: (nameLen: number, kind: number, distributor: number, entriesField: number, indexKey: number, chainField: number, labelKey: number, gainKey: number, panKey: number, muteKey: number, soloKey: number, dryKey: number, wetKey: number, inputTapField: number, crossover1Key: number, crossover2Key: number, crossover3Key: number) => void;
|
|
29
29
|
input_reserve: (len: number) => number;
|
|
30
30
|
};
|
|
@@ -39,6 +39,8 @@ export type CompositeRegistration = {
|
|
|
39
39
|
childEnabledKey: number;
|
|
40
40
|
childMuteKey: number;
|
|
41
41
|
childSoloKey: number;
|
|
42
|
+
childVolumeKey: number;
|
|
43
|
+
childPanKey: number;
|
|
42
44
|
};
|
|
43
45
|
export declare const parseDylink: (module: WebAssembly.Module) => {
|
|
44
46
|
memorySize: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-linker.d.ts","sourceRoot":"","sources":["../src/device-linker.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"device-linker.d.ts","sourceRoot":"","sources":["../src/device-linker.ts"],"names":[],"mappings":"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"}
|
package/dist/device-linker.js
CHANGED
|
@@ -105,7 +105,7 @@ export const linkDevice = (engine, memory, table, module, boxType, sampleRate, b
|
|
|
105
105
|
// Register one COMPOSITE box type (a box hosting a child collection of its own instruments): write its
|
|
106
106
|
// name, then map its child collection fields. The child plugin itself is a normal `linkDevice` entry.
|
|
107
107
|
export const registerComposite = (engine, memory, spec) => {
|
|
108
|
-
engine.composite_register(writeName(engine, memory, spec.boxType), spec.childrenField, spec.indexKey, spec.excludeKey, spec.cellInstrumentField, spec.cellMidiField, spec.cellAudioField, spec.childEnabledKey, spec.childMuteKey, spec.childSoloKey);
|
|
108
|
+
engine.composite_register(writeName(engine, memory, spec.boxType), spec.childrenField, spec.indexKey, spec.excludeKey, spec.cellInstrumentField, spec.cellMidiField, spec.cellAudioField, spec.childEnabledKey, spec.childMuteKey, spec.childSoloKey, spec.childVolumeKey, spec.childPanKey);
|
|
109
109
|
};
|
|
110
110
|
// Register one EFFECT COMPOSITE box type (a parallel fx / midi stack): write its name, then map its entry
|
|
111
111
|
// collection + the entry box's field keys. Its entries are realized by the engine itself, so — unlike a
|
package/dist/engine-exports.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export type EngineExports = {
|
|
|
3
3
|
device_alloc: (size: number) => number;
|
|
4
4
|
device_register: (processIndex: number, stateSize: number, kind: number, initIndex: number, parameterChangedIndex: number, fieldChangedIndex: number, sampleChangedIndex: number, soundfontChangedIndex: number, resetIndex: number, terminateIndex: number, midiEffectsField: number, audioEffectsField: number, paramCollectionField: number, sampleCollectionField: number) => number;
|
|
5
5
|
device_set_box_type: (deviceId: number, nameLen: number) => void;
|
|
6
|
-
composite_register: (nameLen: number, childrenField: number, indexKey: number, excludeKey: number, cellInstrumentField: number, cellMidiField: number, cellAudioField: number, childEnabledKey: number, childMuteKey: number, childSoloKey: number) => void;
|
|
6
|
+
composite_register: (nameLen: number, childrenField: number, indexKey: number, excludeKey: number, cellInstrumentField: number, cellMidiField: number, cellAudioField: number, childEnabledKey: number, childMuteKey: number, childSoloKey: number, childVolumeKey: number, childPanKey: number) => void;
|
|
7
7
|
effect_composite_register: (nameLen: number, kind: number, distributor: number, entriesField: number, indexKey: number, chainField: number, labelKey: number, gainKey: number, panKey: number, muteKey: number, soloKey: number, dryKey: number, wetKey: number, inputTapField: number, crossover1Key: number, crossover2Key: number, crossover3Key: number) => void;
|
|
8
8
|
input_ptr: () => number;
|
|
9
9
|
input_capacity: () => number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine-exports.d.ts","sourceRoot":"","sources":["../src/engine-exports.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG;IACxB,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IAItC,eAAe,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,KAAK,MAAM,CAAA;IAGxX,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAIhE,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"engine-exports.d.ts","sourceRoot":"","sources":["../src/engine-exports.ts"],"names":[],"mappings":"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"}
|
package/dist/engine-modules.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine-modules.d.ts","sourceRoot":"","sources":["../src/engine-modules.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"engine-modules.d.ts","sourceRoot":"","sources":["../src/engine-modules.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,aAAa,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAG7E,mBAAmB,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAE3E,eAAe,EAAE,MAAM,CAAC;IAGxB,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAG3C,cAAc,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAC9C,CAAA;AASD,MAAM,MAAM,mBAAmB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,mBAAmB,CAAA;IACzB,WAAW,EAAE,0BAA0B,CAAA;IACvC,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAC1C,CAAA;AAGD,oBAAY,mBAAmB;IAAE,WAAW,IAAI;IAAE,UAAU,IAAI;CAAC;AAGjE,oBAAY,0BAA0B;IAAE,SAAS,IAAI;IAAE,MAAM,IAAI;IAAE,SAAS,IAAI;CAAC;AAEjF,MAAM,MAAM,aAAa,GAAG;IACxB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAA;IAChC,aAAa,EAAE,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IAChD,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;IACxC,gBAAgB,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAA;CACvD,CAAA;AAQD,eAAO,MAAM,kBAAkB,QAAO,WAAW,CAAC,MAAgD,CAAA;AAMlG,eAAO,MAAM,OAAO,EAAE,aAAa,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA2BnE,CAAA;AAKD,eAAO,MAAM,UAAU,EAAE,aAAa,CAAC,aAAa,CAWnD,CAAA;AAMD,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,mBAAmB,CA0BhE,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAU,OAAM,MAAW,KAAG,OAAO,CAAC,aAAa,CAUhF,CAAA"}
|
package/dist/engine-modules.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
// Fetch + compile the wasm modules the engine worklet needs: the engine (the dynamic-linker host) and
|
|
2
|
+
// the device PLUGINS (PIC side modules the engine loads at host-assigned bases). All are handed to the
|
|
3
|
+
// "engine" AudioWorkletProcessor via processorOptions; the worklet links the devices into the engine.
|
|
2
4
|
// WASM CONTRACT: mirrors abi DEVICE_KIND_* (crates/abi/src/lib.rs).
|
|
3
5
|
export var EffectCompositeKind;
|
|
4
6
|
(function (EffectCompositeKind) {
|
|
@@ -12,27 +14,13 @@ export var EffectCompositeDistributor;
|
|
|
12
14
|
EffectCompositeDistributor[EffectCompositeDistributor["Stereo"] = 1] = "Stereo";
|
|
13
15
|
EffectCompositeDistributor[EffectCompositeDistributor["Frequency"] = 2] = "Frequency";
|
|
14
16
|
})(EffectCompositeDistributor || (EffectCompositeDistributor = {}));
|
|
15
|
-
// The engine's single linear memory:
|
|
16
|
-
//
|
|
17
|
-
// on grow
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
// max=65536, and a smaller provided max still satisfies it (verified: it instantiates down to 8192).
|
|
23
|
-
// Needs cross-origin isolation (COOP/COEP, set in vite.config). Passed into the worklet via processorOptions.
|
|
24
|
-
export const createEngineMemory = () => {
|
|
25
|
-
const initial = 256;
|
|
26
|
-
for (const maximum of [65536, 32768, 16384, 8192]) {
|
|
27
|
-
console.debug(`Try ${maximum} bytes for engine memory...`);
|
|
28
|
-
const memory = Option.tryCatch(() => new WebAssembly.Memory({ initial, maximum, shared: true }));
|
|
29
|
-
if (memory.nonEmpty()) {
|
|
30
|
-
return memory.unwrap();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
// Smallest workable ceiling; if even this throws, the device genuinely cannot host the engine.
|
|
34
|
-
return new WebAssembly.Memory({ initial, maximum: 4096, shared: true });
|
|
35
|
-
};
|
|
17
|
+
// The engine's single linear memory: NON-shared, created INSIDE the worklet/worker that runs the engine
|
|
18
|
+
// (a non-shared memory cannot be postMessaged). Without the shared flag the runtime may RELOCATE the
|
|
19
|
+
// buffer on grow, so no upfront address-space reservation is needed — the reservation ladder that failed
|
|
20
|
+
// on constrained devices (#1030, the Riffle Android crash) is gone; talc grows on demand. The price:
|
|
21
|
+
// every grow DETACHES existing JS views, so views over the memory must be constructed fresh after any
|
|
22
|
+
// allocation (the code does this throughout; long-held broadcast views re-register on buffer change).
|
|
23
|
+
export const createEngineMemory = () => new WebAssembly.Memory({ initial: 256 });
|
|
36
24
|
// The device PIC side modules to load: each wasm plus the device-BOX TYPE it realizes. This is the device
|
|
37
25
|
// table the engine uses to instantiate a device box: when the box graph presents e.g. an ArpeggioDeviceBox,
|
|
38
26
|
// the engine looks up its type here to find its plugin under /wasm/plugins/. Load order is irrelevant now (the engine reads
|
|
@@ -72,13 +60,13 @@ export const COMPOSITES = [
|
|
|
72
60
|
// Playfield: direct children (self-hosting slots, device-declared chains), routed by note index + choke.
|
|
73
61
|
{ boxType: "PlayfieldDeviceBox", childrenField: 10, indexKey: 15, excludeKey: 42,
|
|
74
62
|
cellInstrumentField: 0, cellMidiField: 0, cellAudioField: 0, childEnabledKey: 22,
|
|
75
|
-
childMuteKey: 40, childSoloKey: 41 },
|
|
63
|
+
childMuteKey: 40, childSoloKey: 41, childVolumeKey: 50, childPanKey: 51 },
|
|
76
64
|
// A generic instrument bundle: children are CELLS (CompositeCellBox) at field 10, each wrapping one
|
|
77
65
|
// instrument (field 2) plus its midi-fx (3) and audio-fx (4) chains, ordered by the cell's own `index`
|
|
78
66
|
// (field 5, UI position + engine sort). No note routing, no choke.
|
|
79
67
|
{ boxType: "CompositeDeviceBox", childrenField: 10, indexKey: 5, excludeKey: 0,
|
|
80
68
|
cellInstrumentField: 2, cellMidiField: 3, cellAudioField: 4, childEnabledKey: 0,
|
|
81
|
-
childMuteKey: 0, childSoloKey: 0 }
|
|
69
|
+
childMuteKey: 0, childSoloKey: 0, childVolumeKey: 0, childPanKey: 0 }
|
|
82
70
|
];
|
|
83
71
|
// The EFFECT composite box types (parallel fx / midi stacks). Each hosts its ENTRIES at field 10, ordered by the
|
|
84
72
|
// entry's own `index` (3); an entry holds its chain at field 2, its label at 4, and its gain / mute / solo at
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { UUID } from "@opendaw/lib-std";
|
|
2
1
|
import type { CompositeSpec, EffectCompositeSpec } from "./engine-modules";
|
|
3
2
|
export type WasmEngineAttachment = {
|
|
4
3
|
engineModule: WebAssembly.Module;
|
|
@@ -6,18 +5,11 @@ export type WasmEngineAttachment = {
|
|
|
6
5
|
deviceBoxTypes: ReadonlyArray<string>;
|
|
7
6
|
composites: ReadonlyArray<CompositeSpec>;
|
|
8
7
|
effectComposites: ReadonlyArray<EffectCompositeSpec>;
|
|
9
|
-
memory: WebAssembly.Memory;
|
|
10
8
|
};
|
|
11
9
|
export interface WasmSyncProtocol {
|
|
12
10
|
applyUpdates(bytes: ArrayBuffer): void;
|
|
13
11
|
checksum(bytes: Int8Array): Promise<void>;
|
|
14
12
|
}
|
|
15
|
-
export interface WasmFrozenProtocol {
|
|
16
|
-
frozenAllocate(frameCount: number, channels: number): Promise<number>;
|
|
17
|
-
frozenAttach(uuid: UUID.Bytes, frameCount: number, channels: number, sampleRate: number): void;
|
|
18
|
-
frozenClear(uuid: UUID.Bytes): void;
|
|
19
|
-
}
|
|
20
13
|
export declare const WASM_ENGINE_PROCESSOR_NAME = "engine-wasm-processor";
|
|
21
14
|
export declare const WASM_SYNC_CHANNEL = "engine-sync-bytes";
|
|
22
|
-
export declare const WASM_FROZEN_CHANNEL = "engine-frozen-audio";
|
|
23
15
|
//# sourceMappingURL=protocol.d.ts.map
|
package/dist/protocol.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,mBAAmB,EAAC,MAAM,kBAAkB,CAAA;AAIxE,MAAM,MAAM,oBAAoB,GAAG;IAC/B,YAAY,EAAE,WAAW,CAAC,MAAM,CAAA;IAChC,aAAa,EAAE,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IAChD,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;IACxC,gBAAgB,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAA;CACvD,CAAA;AAMD,MAAM,WAAW,gBAAgB;IAC7B,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5C;AAED,eAAO,MAAM,0BAA0B,0BAA0B,CAAA;AACjE,eAAO,MAAM,iBAAiB,sBAAsB,CAAA"}
|
package/dist/protocol.js
CHANGED
package/dist/wasm/engine.wasm
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|