@carbonenginejs/runtime-resource 0.12.0 → 0.12.1
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/CjsResMan.js +4 -4
- package/dist/CjsResMan.js.map +1 -1
- package/dist/_virtual/_rollupPluginBabelHelpers.js +1 -4
- package/dist/_virtual/_rollupPluginBabelHelpers.js.map +1 -1
- package/dist/format/CjsByteReader.js +310 -0
- package/dist/format/CjsByteReader.js.map +1 -0
- package/dist/format/CjsByteWriter.js +242 -0
- package/dist/format/CjsByteWriter.js.map +1 -0
- package/dist/format/CjsFormatError.js +41 -0
- package/dist/format/CjsFormatError.js.map +1 -0
- package/dist/format/CjsStringTable.js +268 -0
- package/dist/format/CjsStringTable.js.map +1 -0
- package/dist/format/carbonEffect/CjsCarbonEffectReader.js +361 -0
- package/dist/format/carbonEffect/CjsCarbonEffectReader.js.map +1 -0
- package/dist/format/carbonEffect/CjsCarbonEffectWriter.js +373 -0
- package/dist/format/carbonEffect/CjsCarbonEffectWriter.js.map +1 -0
- package/dist/format/carbonEffect/carbonDescriptionFromPortable.js +372 -0
- package/dist/format/carbonEffect/carbonDescriptionFromPortable.js.map +1 -0
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js +427 -0
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js.map +1 -0
- package/dist/format/carbonEffect/carbonEffectRecords.js +955 -0
- package/dist/format/carbonEffect/carbonEffectRecords.js.map +1 -0
- package/dist/format/compareUtf8.js +36 -0
- package/dist/format/compareUtf8.js.map +1 -0
- package/dist/format/index.js +11 -0
- package/dist/format/index.js.map +1 -0
- package/dist/formats/bnk/CjsBnkFormat.js +10 -4
- package/dist/formats/bnk/CjsBnkFormat.js.map +1 -1
- package/dist/formats/bnk/core/eventAction.js +305 -0
- package/dist/formats/bnk/core/eventAction.js.map +1 -0
- package/dist/formats/bnk/core/helpers.js +11 -2
- package/dist/formats/bnk/core/helpers.js.map +1 -1
- package/dist/formats/bnk/core/nodeBase.js +532 -0
- package/dist/formats/bnk/core/nodeBase.js.map +1 -0
- package/dist/formats/bnk/core/sfxNodes.js +252 -152
- package/dist/formats/bnk/core/sfxNodes.js.map +1 -1
- package/dist/formats/hlsl/core/HlslReader.js +7 -257
- package/dist/formats/hlsl/core/HlslReader.js.map +1 -1
- package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js +781 -0
- package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js +21 -1
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js.map +1 -1
- package/dist/formats/index.js +1 -1
- package/dist/formats/webgl/core/cewg/CewgPackage.js +2 -1
- package/dist/formats/webgl/core/cewg/CewgPackage.js.map +1 -1
- package/dist/formats/webgl/core/cewg/binary.js +11 -93
- package/dist/formats/webgl/core/cewg/binary.js.map +1 -1
- package/dist/formats/webgl/core/effectPackage.js +1 -1
- package/dist/formats/webgpu/CjsWebgpuFormat.js +4 -23
- package/dist/formats/webgpu/CjsWebgpuFormat.js.map +1 -1
- package/dist/formats/webgpu/core/buildCarbonEffectContainer.js +197 -0
- package/dist/formats/webgpu/core/buildCarbonEffectContainer.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuContainer.js +368 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuContainer.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/containerViews.js +355 -0
- package/dist/formats/webgpu/core/cewgpu/containerViews.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/validateContainer.js +90 -0
- package/dist/formats/webgpu/core/cewgpu/validateContainer.js.map +1 -0
- package/dist/formats/webgpu/core/effectBackendBodySet.js +21 -20
- package/dist/formats/webgpu/core/effectBackendBodySet.js.map +1 -1
- package/dist/formats/webgpu/core/helpers.js +87 -92
- package/dist/formats/webgpu/core/helpers.js.map +1 -1
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js +14 -13
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js.map +1 -1
- package/dist/formats/webgpu/core/ir/inferValueTypes.js +10 -8
- package/dist/formats/webgpu/core/ir/inferValueTypes.js.map +1 -1
- package/dist/formats/webgpu/core/packageEffect.js +94 -9
- package/dist/formats/webgpu/core/packageEffect.js.map +1 -1
- package/dist/formats/webgpu/core/packageMetadata.js +10 -1
- package/dist/formats/webgpu/core/packageMetadata.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js +17 -15
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js +13 -12
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js +9 -8
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js +23 -22
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js +46 -44
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js.map +1 -1
- package/dist/resource/CjsResource.js +700 -684
- package/dist/resource/CjsResource.js.map +1 -1
- package/dist/resource/Tr2LightProfileRes.js +18 -27
- package/dist/resource/Tr2LightProfileRes.js.map +1 -1
- package/dist/resource/audio/CjsAudioBufferRes.js +2 -2
- package/dist/resource/audio/CjsAudioBufferRes.js.map +1 -1
- package/dist/resource/audio/CjsAudioRes.js +2 -2
- package/dist/resource/audio/CjsAudioRes.js.map +1 -1
- package/dist/resource/geometry/TriGeometryRes.js +605 -586
- package/dist/resource/geometry/TriGeometryRes.js.map +1 -1
- package/dist/resource/geometry/granny/Tr2GrannyStateRes.js +21 -30
- package/dist/resource/geometry/granny/Tr2GrannyStateRes.js.map +1 -1
- package/dist/resource/geometry/granny/TriGrannyRes.js +21 -30
- package/dist/resource/geometry/granny/TriGrannyRes.js.map +1 -1
- package/dist/resource/shader/Tr2EffectRes.js +9 -7
- package/dist/resource/shader/Tr2EffectRes.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialArea.js +5 -3
- package/dist/resource/shader/Tr2MaterialArea.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialMesh.js +4 -2
- package/dist/resource/shader/Tr2MaterialMesh.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialRes.js +5 -3
- package/dist/resource/shader/Tr2MaterialRes.js.map +1 -1
- package/dist/resource/shader/Tr2Shader.js +26 -21
- package/dist/resource/shader/Tr2Shader.js.map +1 -1
- package/dist/resource/shader/Tr2ShaderPermutation.js +8 -6
- package/dist/resource/shader/Tr2ShaderPermutation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDefine.js +5 -3
- package/dist/resource/shader/reflection/Tr2EffectDefine.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDescription.js +5 -3
- package/dist/resource/shader/reflection/Tr2EffectDescription.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js +17 -15
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js +11 -9
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectResource.js +8 -6
- package/dist/resource/shader/reflection/Tr2EffectResource.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js +15 -13
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js +7 -5
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2Pass.js +11 -9
- package/dist/resource/shader/reflection/Tr2Pass.js.map +1 -1
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js +8 -6
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js.map +1 -1
- package/dist/resource/texture/CjsTextureArrayRes.js +400 -411
- package/dist/resource/texture/CjsTextureArrayRes.js.map +1 -1
- package/dist/resource/texture/Tr2ImageRes.js +99 -95
- package/dist/resource/texture/Tr2ImageRes.js.map +1 -1
- package/dist/resource/texture/TriTextureRes.js +312 -273
- package/dist/resource/texture/TriTextureRes.js.map +1 -1
- package/docs/README.md +13 -1
- package/docs/architecture.md +3 -3
- package/docs/concepts/resource-lifecycle.md +9 -2
- package/docs/concepts/shader-resource-model.md +114 -0
- package/docs/concepts/writing-an-engine-adapter.md +115 -0
- package/docs/formats/README.md +24 -1
- package/docs/formats/carbon-effect-container.md +452 -0
- package/docs/formats/dxbc/reference/classes/README.md +5 -72
- package/docs/formats/hlsl/reference/api.md +5 -4
- package/docs/formats/hlsl/reference/classes/README.md +6 -11
- package/docs/formats/provenance.md +23 -13
- package/docs/formats/webgl/reference/classes/README.md +5 -92
- package/docs/formats/webgpu/README.md +19 -16
- package/docs/formats/webgpu/architecture.md +15 -12
- package/docs/formats/webgpu/formats/cewgpu.md +175 -438
- package/docs/formats/webgpu/guides/effect-packaging.md +132 -140
- package/docs/formats/webgpu/reference/api.md +131 -131
- package/docs/formats/webgpu/reference/classes/README.md +5 -62
- package/docs/formats/webgpu/reference/wgsl-compatibility.md +146 -45
- package/docs/formats/wwise.md +34 -8
- package/docs/reference/classes/core.md +80 -0
- package/docs/reference/classes/formats.md +18 -28
- package/docs/reference/events.md +25 -0
- package/docs/reference/motherlode-cache.md +22 -8
- package/docs/reference/workers.md +5 -5
- package/docs/roadmap.md +61 -41
- package/package.json +2 -1
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js +0 -415
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js +0 -100
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/binary.js +0 -93
- package/dist/formats/webgpu/core/cewgpu/binary.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/tags.js +0 -17
- package/dist/formats/webgpu/core/cewgpu/tags.js.map +0 -1
- package/dist/formats/webgpu/core/effectPackageValidation.js +0 -1078
- package/dist/formats/webgpu/core/effectPackageValidation.js.map +0 -1
- package/docs/formats/hlsl/reference/classes/carbon-compatibility.md +0 -66
- package/docs/formats/hlsl/reference/classes/public-api.md +0 -26
- package/docs/formats/hlsl/reference/classes/tr2-effect-model.md +0 -150
|
@@ -1,91 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { WWISE_NODE_BASE_VERSION, parseNodeBaseRange, WwiseCursor, readNodeBase, boundedCount, finite, readInitialRtpcs, readCurvePoints, readInitialRtpc } from './nodeBase.js';
|
|
2
2
|
|
|
3
3
|
// Wwise v150 authored-SFX node decoding. Like musicNodes.js, this interprets
|
|
4
4
|
// inspect() payload views outside the BNK read path and accepts a suffix only
|
|
5
|
-
// when one anchored candidate consumes the payload exactly.
|
|
5
|
+
// when one anchored candidate consumes the payload exactly. Common NodeBase
|
|
6
|
+
// facts and non-playable hierarchy/attenuation objects stay separate from the
|
|
7
|
+
// playback-node map.
|
|
6
8
|
|
|
7
|
-
const SUPPORTED_VERSION =
|
|
9
|
+
const SUPPORTED_VERSION = WWISE_NODE_BASE_VERSION;
|
|
8
10
|
const SFX_CHILD_TYPES = new Set([2, 5, 6, 7, 9]);
|
|
9
11
|
const TYPE_NAMES = Object.freeze({
|
|
10
12
|
2: "sound",
|
|
11
13
|
5: "random-sequence-container",
|
|
12
14
|
6: "switch-container",
|
|
13
|
-
|
|
15
|
+
7: "actor-mixer",
|
|
16
|
+
9: "blend-container",
|
|
17
|
+
14: "attenuation"
|
|
14
18
|
});
|
|
15
19
|
|
|
16
|
-
/**
|
|
17
|
-
* Bounds-aware little-endian cursor used for exact-end Wwise SFX-tail
|
|
18
|
-
* validation.
|
|
19
|
-
*/
|
|
20
|
-
class SfxCursor {
|
|
21
|
-
/** Creates a cursor over one HIRC payload at a candidate tail offset. */
|
|
22
|
-
constructor(bytes, offset = 0) {
|
|
23
|
-
this.bytes = bytes;
|
|
24
|
-
this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
25
|
-
this.at = offset;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Returns the number of unread payload bytes. */
|
|
29
|
-
get remaining() {
|
|
30
|
-
return this.bytes.byteLength - this.at;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** Verifies that a primitive read remains inside the HIRC payload. */
|
|
34
|
-
ensure(size) {
|
|
35
|
-
if (this.at + size > this.bytes.byteLength) {
|
|
36
|
-
throw new RangeError("truncated SFX node");
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Reads an unsigned 8-bit integer. */
|
|
41
|
-
u8() {
|
|
42
|
-
this.ensure(1);
|
|
43
|
-
return this.view.getUint8(this.at++);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Reads an unsigned little-endian 16-bit integer. */
|
|
47
|
-
u16() {
|
|
48
|
-
this.ensure(2);
|
|
49
|
-
const value = this.view.getUint16(this.at, true);
|
|
50
|
-
this.at += 2;
|
|
51
|
-
return value;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Reads an unsigned little-endian 32-bit integer. */
|
|
55
|
-
u32() {
|
|
56
|
-
this.ensure(4);
|
|
57
|
-
const value = this.view.getUint32(this.at, true);
|
|
58
|
-
this.at += 4;
|
|
59
|
-
return value;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Reads a signed little-endian 32-bit integer. */
|
|
63
|
-
s32() {
|
|
64
|
-
this.ensure(4);
|
|
65
|
-
const value = this.view.getInt32(this.at, true);
|
|
66
|
-
this.at += 4;
|
|
67
|
-
return value;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Reads a little-endian 32-bit float. */
|
|
71
|
-
f32() {
|
|
72
|
-
this.ensure(4);
|
|
73
|
-
const value = this.view.getFloat32(this.at, true);
|
|
74
|
-
this.at += 4;
|
|
75
|
-
return value;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** Reads one MSB-first Wwise variable-length unsigned integer. */
|
|
79
|
-
variable() {
|
|
80
|
-
const result = readWwiseVar(this.bytes, this.at);
|
|
81
|
-
if (!result) {
|
|
82
|
-
throw new RangeError("invalid Wwise variable integer");
|
|
83
|
-
}
|
|
84
|
-
this.at = result.nextOffset;
|
|
85
|
-
return result.value;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
20
|
/**
|
|
90
21
|
* Decodes one v150 HIRC 5 Random/Sequence payload.
|
|
91
22
|
*
|
|
@@ -122,6 +53,32 @@ function parseSfxLayer(payload, knownObjects, {
|
|
|
122
53
|
return FindLayer(payload, NormalizeKnownObjects(knownObjects), bankVersion).node;
|
|
123
54
|
}
|
|
124
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Decodes one exact v150 HIRC 7 Actor-Mixer hierarchy object.
|
|
58
|
+
*
|
|
59
|
+
* Actor-Mixers carry inherited NodeBase facts and child identities, but are
|
|
60
|
+
* not themselves playable container behavior.
|
|
61
|
+
*
|
|
62
|
+
* @returns {object|null} Typed hierarchy object, or null when invalid.
|
|
63
|
+
*/
|
|
64
|
+
function parseSfxActorMixer(payload, {
|
|
65
|
+
bankVersion = SUPPORTED_VERSION
|
|
66
|
+
} = {}) {
|
|
67
|
+
return FindActorMixer(payload, bankVersion).node;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Decodes one exact v150 HIRC 14 attenuation object without assigning curve
|
|
72
|
+
* slots semantic names.
|
|
73
|
+
*
|
|
74
|
+
* @returns {object|null} Typed attenuation object, or null when invalid.
|
|
75
|
+
*/
|
|
76
|
+
function parseSfxAttenuation(payload, {
|
|
77
|
+
bankVersion = SUPPORTED_VERSION
|
|
78
|
+
} = {}) {
|
|
79
|
+
return FindAttenuation(payload, bankVersion).node;
|
|
80
|
+
}
|
|
81
|
+
|
|
125
82
|
/**
|
|
126
83
|
* Decodes typed SFX nodes, events, and actions across inspected v150 banks.
|
|
127
84
|
*
|
|
@@ -148,9 +105,13 @@ function sfxNodesFromBanks(inspections) {
|
|
|
148
105
|
}
|
|
149
106
|
}
|
|
150
107
|
const nodes = new Map();
|
|
108
|
+
const nodeBases = new Map();
|
|
109
|
+
const actorMixers = new Map();
|
|
110
|
+
const attenuations = new Map();
|
|
151
111
|
const events = new Map();
|
|
152
112
|
const actions = new Map();
|
|
153
113
|
const failed = [];
|
|
114
|
+
const nodeBaseFailed = [];
|
|
154
115
|
const ambiguous = [];
|
|
155
116
|
const unsupportedVersions = [];
|
|
156
117
|
const parsedByType = {};
|
|
@@ -182,6 +143,7 @@ function sfxNodesFromBanks(inspections) {
|
|
|
182
143
|
bank,
|
|
183
144
|
actionType: entry.actionType,
|
|
184
145
|
targetId: entry.targetId,
|
|
146
|
+
action: entry.action ?? null,
|
|
185
147
|
payload: entry.payload
|
|
186
148
|
});
|
|
187
149
|
continue;
|
|
@@ -210,8 +172,12 @@ function sfxNodesFromBanks(inspections) {
|
|
|
210
172
|
result = FindRandomSequence(entry.payload, knownObjects, version);
|
|
211
173
|
} else if (entry.type === 6) {
|
|
212
174
|
result = FindSwitch(entry.payload, knownObjects, version);
|
|
175
|
+
} else if (entry.type === 7) {
|
|
176
|
+
result = FindActorMixer(entry.payload, version);
|
|
213
177
|
} else if (entry.type === 9) {
|
|
214
178
|
result = FindLayer(entry.payload, knownObjects, version);
|
|
179
|
+
} else if (entry.type === 14) {
|
|
180
|
+
result = FindAttenuation(entry.payload, version);
|
|
215
181
|
} else {
|
|
216
182
|
continue;
|
|
217
183
|
}
|
|
@@ -231,35 +197,179 @@ function sfxNodesFromBanks(inspections) {
|
|
|
231
197
|
}
|
|
232
198
|
parsed++;
|
|
233
199
|
parsedByType[result.node.type] = (parsedByType[result.node.type] ?? 0) + 1;
|
|
234
|
-
|
|
200
|
+
if (entry.type === 14) {
|
|
201
|
+
attenuations.set(entry.id, {
|
|
202
|
+
id: entry.id,
|
|
203
|
+
bank,
|
|
204
|
+
...result.node
|
|
205
|
+
});
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (entry.type === 7) {
|
|
209
|
+
actorMixers.set(entry.id, {
|
|
210
|
+
id: entry.id,
|
|
211
|
+
bank,
|
|
212
|
+
...result.node
|
|
213
|
+
});
|
|
214
|
+
nodeBases.set(entry.id, result.node.nodeBase);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const node = {
|
|
235
218
|
id: entry.id,
|
|
236
219
|
bank,
|
|
237
220
|
...result.node
|
|
238
|
-
}
|
|
221
|
+
};
|
|
222
|
+
const nodeBaseResult = ReadEntryNodeBase(entry, result, version);
|
|
223
|
+
nodes.set(entry.id, node);
|
|
224
|
+
if (nodeBaseResult.nodeBase) {
|
|
225
|
+
nodeBases.set(entry.id, nodeBaseResult.nodeBase);
|
|
226
|
+
} else {
|
|
227
|
+
nodeBaseFailed.push({
|
|
228
|
+
bank,
|
|
229
|
+
version,
|
|
230
|
+
type: TYPE_NAMES[entry.type],
|
|
231
|
+
id: entry.id,
|
|
232
|
+
reason: nodeBaseResult.reason
|
|
233
|
+
});
|
|
234
|
+
}
|
|
239
235
|
}
|
|
240
236
|
}
|
|
241
237
|
return {
|
|
242
238
|
nodes,
|
|
239
|
+
nodeBases,
|
|
240
|
+
actorMixers,
|
|
241
|
+
attenuations,
|
|
243
242
|
events,
|
|
244
243
|
actions,
|
|
245
244
|
diagnostics: {
|
|
246
245
|
parsed,
|
|
247
246
|
parsedByType,
|
|
248
247
|
failed,
|
|
248
|
+
nodeBaseFailed,
|
|
249
249
|
ambiguous,
|
|
250
250
|
unsupportedVersions,
|
|
251
251
|
duplicates
|
|
252
252
|
}
|
|
253
253
|
};
|
|
254
254
|
}
|
|
255
|
+
function ReadEntryNodeBase(entry, result, bankVersion) {
|
|
256
|
+
if (entry.type === 2) {
|
|
257
|
+
const start = SoundNodeBaseOffset(entry);
|
|
258
|
+
if (start === null) {
|
|
259
|
+
return {
|
|
260
|
+
nodeBase: null,
|
|
261
|
+
reason: "sound NodeBase offset is unavailable"
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const nodeBase = parseNodeBaseRange(entry.payload, start, entry.payload.byteLength, {
|
|
265
|
+
bankVersion
|
|
266
|
+
});
|
|
267
|
+
return {
|
|
268
|
+
nodeBase,
|
|
269
|
+
reason: nodeBase ? "" : "sound NodeBase did not consume its exact byte range"
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
if (result.anchor === undefined) {
|
|
273
|
+
return {
|
|
274
|
+
nodeBase: null,
|
|
275
|
+
reason: "container NodeBase anchor is unavailable"
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
const nodeBase = parseNodeBaseRange(entry.payload, 0, result.anchor, {
|
|
279
|
+
bankVersion
|
|
280
|
+
});
|
|
281
|
+
return {
|
|
282
|
+
nodeBase,
|
|
283
|
+
reason: nodeBase ? "" : "container NodeBase did not consume its exact byte range"
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function SoundNodeBaseOffset(entry) {
|
|
287
|
+
const payload = entry?.payload;
|
|
288
|
+
if (!(payload instanceof Uint8Array) || payload.byteLength < 14) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
const pluginType = Number(entry.pluginType ?? entry.pluginId & 0x0f);
|
|
292
|
+
if (pluginType !== 2) {
|
|
293
|
+
return 14;
|
|
294
|
+
}
|
|
295
|
+
if (payload.byteLength < 18) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);
|
|
299
|
+
const parameterSize = view.getUint32(14, true);
|
|
300
|
+
const start = 18 + parameterSize;
|
|
301
|
+
return Number.isSafeInteger(start) && start <= payload.byteLength ? start : null;
|
|
302
|
+
}
|
|
303
|
+
function FindActorMixer(payload, bankVersion) {
|
|
304
|
+
return ParseExact(payload, bankVersion, cursor => {
|
|
305
|
+
const nodeBase = readNodeBase(cursor);
|
|
306
|
+
const count = boundedCount(cursor.u32(), cursor.remaining, 4, 8192);
|
|
307
|
+
const children = [];
|
|
308
|
+
for (let index = 0; index < count; index++) {
|
|
309
|
+
children.push(cursor.u32());
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
type: "actor-mixer",
|
|
313
|
+
nodeBase,
|
|
314
|
+
children
|
|
315
|
+
};
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
function FindAttenuation(payload, bankVersion) {
|
|
319
|
+
return ParseExact(payload, bankVersion, cursor => {
|
|
320
|
+
const heightSpreadRaw = cursor.u8();
|
|
321
|
+
const coneFlags = cursor.u8();
|
|
322
|
+
let cone = null;
|
|
323
|
+
if (coneFlags & 0x01) {
|
|
324
|
+
cone = {
|
|
325
|
+
insideDegrees: finite(cursor.f32()),
|
|
326
|
+
outsideDegrees: finite(cursor.f32()),
|
|
327
|
+
outsideVolume: finite(cursor.f32()),
|
|
328
|
+
lowPass: finite(cursor.f32()),
|
|
329
|
+
highPass: finite(cursor.f32())
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
const curveToUse = [];
|
|
333
|
+
for (let index = 0; index < 19; index++) {
|
|
334
|
+
curveToUse.push(cursor.s8());
|
|
335
|
+
}
|
|
336
|
+
const curveCount = boundedCount(cursor.u8(), cursor.remaining, 3, 19);
|
|
337
|
+
const curves = [];
|
|
338
|
+
for (let index = 0; index < curveCount; index++) {
|
|
339
|
+
const scaling = cursor.u8();
|
|
340
|
+
const pointCount = boundedCount(cursor.u16(), cursor.remaining, 12, 65535);
|
|
341
|
+
const rtpc = ReadInitialRTPCFromCurve(cursor, scaling, pointCount);
|
|
342
|
+
curves.push(rtpc);
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
type: "attenuation",
|
|
346
|
+
heightSpreadRaw,
|
|
347
|
+
heightSpread: Boolean(heightSpreadRaw),
|
|
348
|
+
coneFlags,
|
|
349
|
+
cone,
|
|
350
|
+
curveToUse,
|
|
351
|
+
curves,
|
|
352
|
+
rtpcs: readInitialRtpcs(cursor)
|
|
353
|
+
};
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
function ReadInitialRTPCFromCurve(cursor, scaling, pointCount) {
|
|
357
|
+
if (![0, 2, 3, 4].includes(scaling)) {
|
|
358
|
+
throw new RangeError("invalid attenuation curve scaling");
|
|
359
|
+
}
|
|
360
|
+
return {
|
|
361
|
+
scaling,
|
|
362
|
+
points: readCurvePoints(cursor, pointCount)
|
|
363
|
+
};
|
|
364
|
+
}
|
|
255
365
|
function FindRandomSequence(payload, knownObjects, bankVersion) {
|
|
256
366
|
return FindUnique(payload, bankVersion, cursor => {
|
|
257
367
|
const loopCount = cursor.u16();
|
|
258
368
|
const loopModMin = cursor.u16();
|
|
259
369
|
const loopModMax = cursor.u16();
|
|
260
|
-
const transitionTime =
|
|
261
|
-
const transitionTimeModMin =
|
|
262
|
-
const transitionTimeModMax =
|
|
370
|
+
const transitionTime = finite(cursor.f32());
|
|
371
|
+
const transitionTimeModMin = finite(cursor.f32());
|
|
372
|
+
const transitionTimeModMax = finite(cursor.f32());
|
|
263
373
|
const avoidRepeatCount = cursor.u16();
|
|
264
374
|
const transitionMode = cursor.u8();
|
|
265
375
|
const randomMode = cursor.u8();
|
|
@@ -269,7 +379,7 @@ function FindRandomSequence(payload, knownObjects, bankVersion) {
|
|
|
269
379
|
throw new RangeError("invalid Random/Sequence enum");
|
|
270
380
|
}
|
|
271
381
|
const children = ReadChildren(cursor, knownObjects);
|
|
272
|
-
const playlistCount =
|
|
382
|
+
const playlistCount = boundedCount(cursor.u16(), cursor.remaining, 8, 8192);
|
|
273
383
|
const childSet = new Set(children);
|
|
274
384
|
const playlist = [];
|
|
275
385
|
for (let index = 0; index < playlistCount; index++) {
|
|
@@ -314,18 +424,14 @@ function FindSwitch(payload, knownObjects, bankVersion) {
|
|
|
314
424
|
throw new RangeError("invalid Switch enum");
|
|
315
425
|
}
|
|
316
426
|
const children = ReadChildren(cursor, knownObjects);
|
|
317
|
-
const
|
|
318
|
-
const assignmentCount = BoundedCount(cursor.u32(), cursor.remaining, 8, 8192);
|
|
427
|
+
const assignmentCount = boundedCount(cursor.u32(), cursor.remaining, 8, 8192);
|
|
319
428
|
const assignments = [];
|
|
320
429
|
for (let index = 0; index < assignmentCount; index++) {
|
|
321
430
|
const valueId = cursor.u32();
|
|
322
|
-
const itemCount =
|
|
431
|
+
const itemCount = boundedCount(cursor.u32(), cursor.remaining, 4, 8192);
|
|
323
432
|
const childIds = [];
|
|
324
433
|
for (let item = 0; item < itemCount; item++) {
|
|
325
434
|
const childId = cursor.u32();
|
|
326
|
-
if (!childSet.has(childId)) {
|
|
327
|
-
throw new RangeError("invalid Switch assignment child");
|
|
328
|
-
}
|
|
329
435
|
childIds.push(childId);
|
|
330
436
|
}
|
|
331
437
|
assignments.push({
|
|
@@ -333,14 +439,14 @@ function FindSwitch(payload, knownObjects, bankVersion) {
|
|
|
333
439
|
childIds
|
|
334
440
|
});
|
|
335
441
|
}
|
|
336
|
-
const parameterCount =
|
|
442
|
+
const parameterCount = boundedCount(cursor.u32(), cursor.remaining, 14, 8192);
|
|
337
443
|
const parameters = [];
|
|
338
444
|
for (let index = 0; index < parameterCount; index++) {
|
|
339
445
|
const childId = cursor.u32();
|
|
340
446
|
const flags1 = cursor.u8();
|
|
341
447
|
const flags2 = cursor.u8();
|
|
342
448
|
const onSwitchMode = flags2 & 0x07;
|
|
343
|
-
if (
|
|
449
|
+
if (flags1 & ~0x03 || flags2 & ~0x07 || onSwitchMode > 1) {
|
|
344
450
|
throw new RangeError("invalid Switch parameter");
|
|
345
451
|
}
|
|
346
452
|
parameters.push({
|
|
@@ -352,6 +458,10 @@ function FindSwitch(payload, knownObjects, bankVersion) {
|
|
|
352
458
|
fadeInMs: cursor.s32()
|
|
353
459
|
});
|
|
354
460
|
}
|
|
461
|
+
|
|
462
|
+
// Essential and partial banks may retain raw SwitchList and parameter
|
|
463
|
+
// references to nodes that are not serialized in direct Children.
|
|
464
|
+
// Consumers decide whether those referenced nodes are available.
|
|
355
465
|
return {
|
|
356
466
|
type: "switch",
|
|
357
467
|
groupType,
|
|
@@ -368,31 +478,31 @@ function FindLayer(payload, knownObjects, bankVersion) {
|
|
|
368
478
|
return FindUnique(payload, bankVersion, cursor => {
|
|
369
479
|
const children = ReadChildren(cursor, knownObjects);
|
|
370
480
|
const childSet = new Set(children);
|
|
371
|
-
const layerCount =
|
|
481
|
+
const layerCount = boundedCount(cursor.u32(), cursor.remaining, 15, 1024);
|
|
372
482
|
const layers = [];
|
|
373
483
|
for (let index = 0; index < layerCount; index++) {
|
|
374
484
|
const layerId = cursor.u32();
|
|
375
|
-
const initialRtpcCount =
|
|
485
|
+
const initialRtpcCount = boundedCount(cursor.u16(), cursor.remaining, 14, 4096);
|
|
376
486
|
const initialRtpcs = [];
|
|
377
487
|
for (let rtpc = 0; rtpc < initialRtpcCount; rtpc++) {
|
|
378
|
-
initialRtpcs.push(
|
|
488
|
+
initialRtpcs.push(readInitialRtpc(cursor));
|
|
379
489
|
}
|
|
380
490
|
const controlId = cursor.u32();
|
|
381
491
|
const controlType = cursor.u8();
|
|
382
|
-
const associationCount =
|
|
492
|
+
const associationCount = boundedCount(cursor.u32(), cursor.remaining, 8, 8192);
|
|
383
493
|
const associations = [];
|
|
384
494
|
if (controlType > 4) {
|
|
385
495
|
throw new RangeError("invalid Layer control type");
|
|
386
496
|
}
|
|
387
497
|
for (let association = 0; association < associationCount; association++) {
|
|
388
498
|
const childId = cursor.u32();
|
|
389
|
-
const pointCount =
|
|
499
|
+
const pointCount = boundedCount(cursor.u32(), cursor.remaining, 12, 65535);
|
|
390
500
|
if (!childSet.has(childId)) {
|
|
391
501
|
throw new RangeError("invalid Layer association child");
|
|
392
502
|
}
|
|
393
503
|
associations.push({
|
|
394
504
|
childId,
|
|
395
|
-
points:
|
|
505
|
+
points: readCurvePoints(cursor, pointCount)
|
|
396
506
|
});
|
|
397
507
|
}
|
|
398
508
|
layers.push({
|
|
@@ -415,46 +525,8 @@ function FindLayer(payload, knownObjects, bankVersion) {
|
|
|
415
525
|
};
|
|
416
526
|
});
|
|
417
527
|
}
|
|
418
|
-
function ReadInitialRTPC(cursor) {
|
|
419
|
-
const controlId = cursor.u32();
|
|
420
|
-
const controlType = cursor.u8();
|
|
421
|
-
const accumulation = cursor.u8();
|
|
422
|
-
const parameterId = cursor.variable();
|
|
423
|
-
const curveId = cursor.u32();
|
|
424
|
-
const scaling = cursor.u8();
|
|
425
|
-
const pointCount = BoundedCount(cursor.u16(), cursor.remaining, 12, 65535);
|
|
426
|
-
if (controlType > 4 || accumulation > 6 || scaling > 5) {
|
|
427
|
-
throw new RangeError("invalid initial RTPC enum");
|
|
428
|
-
}
|
|
429
|
-
return {
|
|
430
|
-
controlId,
|
|
431
|
-
controlType,
|
|
432
|
-
accumulation,
|
|
433
|
-
parameterId,
|
|
434
|
-
curveId,
|
|
435
|
-
scaling,
|
|
436
|
-
points: ReadPoints(cursor, pointCount)
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
function ReadPoints(cursor, count) {
|
|
440
|
-
const points = [];
|
|
441
|
-
for (let index = 0; index < count; index++) {
|
|
442
|
-
const from = Finite(cursor.f32());
|
|
443
|
-
const to = Finite(cursor.f32());
|
|
444
|
-
const interpolation = cursor.u32();
|
|
445
|
-
if (interpolation > 9) {
|
|
446
|
-
throw new RangeError("invalid curve interpolation");
|
|
447
|
-
}
|
|
448
|
-
points.push({
|
|
449
|
-
from,
|
|
450
|
-
to,
|
|
451
|
-
interpolation
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
return points;
|
|
455
|
-
}
|
|
456
528
|
function ReadChildren(cursor, knownObjects) {
|
|
457
|
-
const count =
|
|
529
|
+
const count = boundedCount(cursor.u32(), cursor.remaining, 4, 8192);
|
|
458
530
|
const children = [];
|
|
459
531
|
for (let index = 0; index < count; index++) {
|
|
460
532
|
const id = cursor.u32();
|
|
@@ -476,10 +548,13 @@ function FindUnique(payload, bankVersion, parse) {
|
|
|
476
548
|
const candidates = [];
|
|
477
549
|
for (let anchor = 0; anchor < payload.byteLength; anchor++) {
|
|
478
550
|
try {
|
|
479
|
-
const cursor = new
|
|
551
|
+
const cursor = new WwiseCursor(payload, anchor);
|
|
480
552
|
const node = parse(cursor);
|
|
481
553
|
if (cursor.at === payload.byteLength) {
|
|
482
|
-
candidates.push(
|
|
554
|
+
candidates.push({
|
|
555
|
+
node,
|
|
556
|
+
anchor
|
|
557
|
+
});
|
|
483
558
|
}
|
|
484
559
|
} catch {
|
|
485
560
|
// This byte was not the exact type-tail anchor.
|
|
@@ -487,15 +562,52 @@ function FindUnique(payload, bankVersion, parse) {
|
|
|
487
562
|
}
|
|
488
563
|
if (candidates.length === 1) {
|
|
489
564
|
return {
|
|
490
|
-
node: candidates[0],
|
|
565
|
+
node: candidates[0].node,
|
|
566
|
+
anchor: candidates[0].anchor,
|
|
491
567
|
reason: ""
|
|
492
568
|
};
|
|
493
569
|
}
|
|
570
|
+
if (candidates.length > 1) {
|
|
571
|
+
const exactNodeBase = candidates.filter(candidate => parseNodeBaseRange(payload, 0, candidate.anchor, {
|
|
572
|
+
bankVersion
|
|
573
|
+
}));
|
|
574
|
+
if (exactNodeBase.length === 1) {
|
|
575
|
+
return {
|
|
576
|
+
node: exactNodeBase[0].node,
|
|
577
|
+
anchor: exactNodeBase[0].anchor,
|
|
578
|
+
reason: ""
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
}
|
|
494
582
|
return {
|
|
495
583
|
node: null,
|
|
496
584
|
reason: candidates.length ? "ambiguous anchors" : "no exact anchor"
|
|
497
585
|
};
|
|
498
586
|
}
|
|
587
|
+
function ParseExact(payload, bankVersion, parse) {
|
|
588
|
+
if (!(payload instanceof Uint8Array) || Number(bankVersion) !== SUPPORTED_VERSION) {
|
|
589
|
+
return {
|
|
590
|
+
node: null,
|
|
591
|
+
reason: "unsupported bank version"
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
try {
|
|
595
|
+
const cursor = new WwiseCursor(payload);
|
|
596
|
+
const node = parse(cursor);
|
|
597
|
+
return cursor.at === payload.byteLength ? {
|
|
598
|
+
node,
|
|
599
|
+
reason: ""
|
|
600
|
+
} : {
|
|
601
|
+
node: null,
|
|
602
|
+
reason: "trailing bytes"
|
|
603
|
+
};
|
|
604
|
+
} catch (cause) {
|
|
605
|
+
return {
|
|
606
|
+
node: null,
|
|
607
|
+
reason: cause instanceof Error ? cause.message : "invalid object"
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
}
|
|
499
611
|
function NormalizeKnownObjects(value) {
|
|
500
612
|
if (value instanceof Map) {
|
|
501
613
|
return value;
|
|
@@ -515,18 +627,6 @@ function NormalizeKnownObjects(value) {
|
|
|
515
627
|
function KnownType(value) {
|
|
516
628
|
return typeof value === "number" ? value : value?.type;
|
|
517
629
|
}
|
|
518
|
-
function BoundedCount(value, remaining, stride, maximum) {
|
|
519
|
-
if (!Number.isSafeInteger(value) || value < 0 || value > maximum || value * stride > remaining) {
|
|
520
|
-
throw new RangeError("invalid SFX node count");
|
|
521
|
-
}
|
|
522
|
-
return value;
|
|
523
|
-
}
|
|
524
|
-
function Finite(value) {
|
|
525
|
-
if (!Number.isFinite(value)) {
|
|
526
|
-
throw new RangeError("non-finite SFX node value");
|
|
527
|
-
}
|
|
528
|
-
return value;
|
|
529
|
-
}
|
|
530
630
|
|
|
531
|
-
export { parseSfxLayer, parseSfxRandomSequence, parseSfxSwitch, sfxNodesFromBanks };
|
|
631
|
+
export { parseSfxActorMixer, parseSfxAttenuation, parseSfxLayer, parseSfxRandomSequence, parseSfxSwitch, sfxNodesFromBanks };
|
|
532
632
|
//# sourceMappingURL=sfxNodes.js.map
|