@onda-lang/webaudio 0.8.21 → 0.8.23
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/README.md +8 -2
- package/api.md +4 -0
- package/package.json +2 -2
- package/src/index.d.ts +2 -0
- package/src/index.js +10 -0
- package/src/param-metadata.js +45 -21
- package/src/worklet.js +4 -0
package/README.md
CHANGED
|
@@ -56,8 +56,14 @@ block, independently of Web Audio callback sizes; durations at most one block ar
|
|
|
56
56
|
Integer, boolean, and stepped controls update directly. Initial parameters and reinitialization
|
|
57
57
|
settle immediately. A new target restarts from the published value, while repeated writes of the
|
|
58
58
|
same target preserve its deadline. Host ramps are excluded from processor snapshots. The browser
|
|
59
|
-
playground
|
|
60
|
-
|
|
59
|
+
playground defaults to `0.03` seconds (30 ms), with a live **Smooth** control in its Params header
|
|
60
|
+
that remembers the duration in the browser. Explicit DSP smoothing can interpolate within a block.
|
|
61
|
+
|
|
62
|
+
`setParamSmoothingSeconds(seconds)` changes the duration live without recompilation or
|
|
63
|
+
reinitialization. Active ramps restart from the current published value with the new duration.
|
|
64
|
+
Setting 0 (or a duration at most one block) settles active targets immediately and disables ramps;
|
|
65
|
+
smoothing can be enabled later. The duration must be finite and nonnegative, and affects continuous
|
|
66
|
+
float writes from UI controls and automation alike.
|
|
61
67
|
|
|
62
68
|
`resetParams()` restores all declared defaults immediately and cancels host ramps without resetting
|
|
63
69
|
DSP state.
|
package/api.md
CHANGED
|
@@ -223,6 +223,10 @@ The adapter exposes its `node` and validated `metadata`, plus these operations:
|
|
|
223
223
|
- `setParam(nameOrIndex, plain)` and `setParamNormalized(nameOrIndex, normalized)` for whole
|
|
224
224
|
parameters.
|
|
225
225
|
- `resetParams()` to restore parameter defaults immediately and cancel host ramps, retaining DSP state.
|
|
226
|
+
- `setParamSmoothingSeconds(seconds)` to change the host duration live without recompiling or
|
|
227
|
+
reinitializing DSP state. Finite, nonnegative durations are required. Active ramps restart from
|
|
228
|
+
their current values using the new duration; 0 (or a duration at most one block) settles their
|
|
229
|
+
targets immediately. Smoothing can be enabled after starting with 0.
|
|
226
230
|
- `setParamElement(nameOrIndex, element, plain)` and
|
|
227
231
|
`setParamElementNormalized(nameOrIndex, element, normalized)` for one scalar or fixed-array
|
|
228
232
|
element.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onda-lang/webaudio",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Optional Web Audio adapter for Onda processor WebAssembly artifacts",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"prepack": "node ../../scripts/stage-web-api-docs.mjs"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@onda-lang/processor-abi": "0.8.
|
|
37
|
+
"@onda-lang/processor-abi": "0.8.23"
|
|
38
38
|
},
|
|
39
39
|
"publishConfig": {
|
|
40
40
|
"access": "public"
|
package/src/index.d.ts
CHANGED
|
@@ -134,6 +134,8 @@ export class OndaAudioProcessor {
|
|
|
134
134
|
setParam(param: string | number, value: unknown): Promise<any>;
|
|
135
135
|
/** Restore all parameter defaults immediately, cancelling host ramps and retaining DSP state. */
|
|
136
136
|
resetParams(): Promise<any>;
|
|
137
|
+
/** Change host smoothing live, restarting active ramps from their current values; 0 settles them immediately. */
|
|
138
|
+
setParamSmoothingSeconds(seconds: number): Promise<any>;
|
|
137
139
|
/** Set one scalar or fixed-array parameter element without modifying its siblings. */
|
|
138
140
|
setParamElement(param: string | number, element: number, value: unknown): Promise<any>;
|
|
139
141
|
/** Map a host value in [0, 1] through the descriptor and set the resulting plain value. */
|
package/src/index.js
CHANGED
|
@@ -660,6 +660,16 @@ export class OndaAudioProcessor {
|
|
|
660
660
|
}
|
|
661
661
|
}
|
|
662
662
|
|
|
663
|
+
setParamSmoothingSeconds(seconds) {
|
|
664
|
+
try {
|
|
665
|
+
paramSmoothingSamples(seconds, this.metadata?.compile?.sample_rate ?? 1,
|
|
666
|
+
this.metadata?.compile?.block_size ?? 0);
|
|
667
|
+
return this.request("set-param-smoothing", { seconds });
|
|
668
|
+
} catch (error) {
|
|
669
|
+
return Promise.reject(error);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
663
673
|
resetParams() {
|
|
664
674
|
return this.request("reset-params");
|
|
665
675
|
}
|
package/src/param-metadata.js
CHANGED
|
@@ -48,29 +48,55 @@ export class ParamSmoothing {
|
|
|
48
48
|
this.started = false;
|
|
49
49
|
this.addresses = new Map();
|
|
50
50
|
this.entries = [];
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
target: value, elapsed: samples, active: false });
|
|
64
|
-
}
|
|
65
|
-
this.addresses.set(param, elements);
|
|
51
|
+
for (const param of params) {
|
|
52
|
+
if ((param.scalar !== "f32" && param.scalar !== "f64")
|
|
53
|
+
|| param.param_control?.step_count != null) continue;
|
|
54
|
+
const elements = [];
|
|
55
|
+
const f32 = param.scalar === "f32";
|
|
56
|
+
for (let element = 0; element < param.array_len; element += 1) {
|
|
57
|
+
const offset = Number(param.byte_offset) + element * (f32 ? 4 : 8);
|
|
58
|
+
const value = f32 ? view.getFloat32(paramsPtr + offset, true)
|
|
59
|
+
: view.getFloat64(paramsPtr + offset, true);
|
|
60
|
+
elements.push(this.entries.length);
|
|
61
|
+
this.entries.push({ offset, f32, current: value, start: value,
|
|
62
|
+
target: value, elapsed: samples, active: false });
|
|
66
63
|
}
|
|
64
|
+
this.addresses.set(param, elements);
|
|
67
65
|
}
|
|
68
66
|
this.active = new Uint32Array(this.entries.length);
|
|
69
67
|
this.activeCount = 0;
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
isEnabledFor(param) {
|
|
73
|
-
return this.addresses.has(param);
|
|
71
|
+
return this.samples > 0 && this.addresses.has(param);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
setDuration(samples, view, paramsPtr) {
|
|
75
|
+
if (samples === this.samples) return;
|
|
76
|
+
// Bulk writes bypass ramp state while disabled; read the actual DSP values.
|
|
77
|
+
if (this.samples === 0) this.readTargets(view, paramsPtr);
|
|
78
|
+
const previousSamples = this.samples;
|
|
79
|
+
this.samples = samples;
|
|
80
|
+
this.inverseSamples = 1 / Math.max(samples, 1);
|
|
81
|
+
for (let cursor = 0; cursor < this.activeCount; cursor += 1) {
|
|
82
|
+
const entry = this.entries[this.active[cursor]];
|
|
83
|
+
if (samples === 0) {
|
|
84
|
+
this.write(entry, entry.target, view, paramsPtr);
|
|
85
|
+
entry.active = false;
|
|
86
|
+
}
|
|
87
|
+
entry.start = entry.current;
|
|
88
|
+
entry.elapsed = entry.elapsed === previousSamples ? samples : 0;
|
|
89
|
+
}
|
|
90
|
+
if (samples === 0) this.activeCount = 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
readTargets(view, paramsPtr) {
|
|
94
|
+
for (const entry of this.entries) {
|
|
95
|
+
entry.current = entry.target = entry.f32
|
|
96
|
+
? view.getFloat32(paramsPtr + entry.offset, true)
|
|
97
|
+
: view.getFloat64(paramsPtr + entry.offset, true);
|
|
98
|
+
entry.start = entry.current;
|
|
99
|
+
}
|
|
74
100
|
}
|
|
75
101
|
|
|
76
102
|
setTarget(param, element, value, initialized) {
|
|
@@ -78,7 +104,7 @@ export class ParamSmoothing {
|
|
|
78
104
|
if (id === undefined) return false;
|
|
79
105
|
const entry = this.entries[id];
|
|
80
106
|
const target = entry.f32 ? Math.fround(Number(value)) : Number(value);
|
|
81
|
-
if (!initialized || !this.started || !Number.isFinite(target) || !Number.isFinite(entry.current)) {
|
|
107
|
+
if (this.samples === 0 || !initialized || !this.started || !Number.isFinite(target) || !Number.isFinite(entry.current)) {
|
|
82
108
|
entry.current = target;
|
|
83
109
|
entry.target = target;
|
|
84
110
|
entry.elapsed = this.samples;
|
|
@@ -123,6 +149,7 @@ export class ParamSmoothing {
|
|
|
123
149
|
}
|
|
124
150
|
|
|
125
151
|
settle(view, paramsPtr) {
|
|
152
|
+
if (this.samples === 0) this.readTargets(view, paramsPtr);
|
|
126
153
|
this.activeCount = 0;
|
|
127
154
|
this.started = false;
|
|
128
155
|
for (const entry of this.entries) {
|
|
@@ -134,10 +161,7 @@ export class ParamSmoothing {
|
|
|
134
161
|
}
|
|
135
162
|
|
|
136
163
|
reset(view, paramsPtr) {
|
|
137
|
-
|
|
138
|
-
entry.target = entry.f32 ? view.getFloat32(paramsPtr + entry.offset, true)
|
|
139
|
-
: view.getFloat64(paramsPtr + entry.offset, true);
|
|
140
|
-
}
|
|
164
|
+
this.readTargets(view, paramsPtr);
|
|
141
165
|
this.settle(view, paramsPtr);
|
|
142
166
|
}
|
|
143
167
|
|
package/src/worklet.js
CHANGED
|
@@ -748,6 +748,10 @@ class OndaWasmProcessor extends AudioWorkletProcessor {
|
|
|
748
748
|
message.element ?? null,
|
|
749
749
|
);
|
|
750
750
|
this.postResponse(message, { type: "onda-ok", operation: message.type });
|
|
751
|
+
} else if (message.type === "set-param-smoothing") {
|
|
752
|
+
const samples = paramSmoothingSamples(message.seconds, this.compileSampleRate, this.blockSize);
|
|
753
|
+
this.paramSmoothing.setDuration(samples, this.memoryView(), this.paramsPtr);
|
|
754
|
+
this.postResponse(message, { type: "onda-ok", operation: message.type });
|
|
751
755
|
} else if (message.type === "reset-params") {
|
|
752
756
|
this.writeParamDefaults();
|
|
753
757
|
this.paramSmoothing.reset(this.memoryView(), this.paramsPtr);
|