@woosh/meep-engine 3.46.0 → 3.47.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/editor/actions/concrete/TransformModifyAction.d.ts.map +1 -1
- package/editor/actions/concrete/TransformModifyAction.js +10 -2
- package/editor/ecs/component/FieldDescriptor.js +15 -0
- package/editor/ecs/component/createObjectEditor.js +41 -12
- package/editor/ecs/component/editors/ecs/Transform64Editor.d.ts.map +1 -1
- package/editor/ecs/component/editors/ecs/Transform64Editor.js +77 -70
- package/editor/tools/TransformToolV2.d.ts.map +1 -1
- package/editor/tools/TransformToolV2.js +4 -0
- package/editor/tools/v2/TransformControls.d.ts.map +1 -1
- package/editor/tools/v2/TransformControls.js +7 -0
- package/editor/view/ecs/EntityEditor.d.ts.map +1 -1
- package/editor/view/ecs/EntityEditor.js +4 -2
- package/package.json +1 -1
- package/src/core/collection/array/array_insert_at.d.ts +16 -0
- package/src/core/collection/array/array_insert_at.d.ts.map +1 -0
- package/src/core/collection/array/array_insert_at.js +32 -0
- package/src/core/collection/array/array_remove_at.d.ts +15 -0
- package/src/core/collection/array/array_remove_at.d.ts.map +1 -0
- package/src/core/collection/array/array_remove_at.js +30 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts +37 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.js +172 -0
- package/src/core/geom/Quaternion.d.ts +1 -0
- package/src/core/geom/Quaternion.d.ts.map +1 -1
- package/src/core/geom/Quaternion.js +12 -48
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +9 -4
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +10 -0
- package/src/engine/ecs/transform/t64_look_rotation.d.ts +4 -4
- package/src/engine/ecs/transform/t64_look_rotation.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_look_rotation.js +7 -18
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +30 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +6 -0
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.js +72 -29
- package/src/engine/input/devices/KeyboardDevice.d.ts +1 -0
- package/src/engine/input/devices/KeyboardDevice.d.ts.map +1 -1
- package/src/engine/input/devices/KeyboardDevice.js +7 -6
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.d.ts.map +1 -1
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +15 -2
- package/src/engine/network/CONGESTION_CONTROL.md +9 -9
- package/src/engine/network/MESSAGE_TRANSPORT.md +364 -0
- package/src/engine/network/NetworkSession.d.ts +31 -11
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +453 -286
- package/src/engine/network/README.md +77 -27
- package/src/engine/network/SMOOTHNESS_DESIGN.md +13 -5
- package/src/engine/network/diagnostics/BandwidthMeter.d.ts +1 -1
- package/src/engine/network/diagnostics/BandwidthMeter.js +1 -1
- package/src/engine/network/orchestrator/HostJoin.d.ts +111 -0
- package/src/engine/network/orchestrator/HostJoin.d.ts.map +1 -0
- package/src/engine/network/orchestrator/HostJoin.js +271 -0
- package/src/engine/network/orchestrator/NetworkPeer.d.ts +151 -112
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +450 -499
- package/src/engine/network/orchestrator/PendingSlices.d.ts +30 -0
- package/src/engine/network/orchestrator/PendingSlices.d.ts.map +1 -0
- package/src/engine/network/orchestrator/PendingSlices.js +83 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts +34 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts.map +1 -0
- package/src/engine/network/orchestrator/ReliableFrames.js +96 -0
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +77 -10
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +236 -61
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +20 -6
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +33 -8
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +7 -1
- package/src/engine/network/sim/ActionLog.d.ts +32 -5
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +47 -5
- package/src/engine/network/sim/SimActionExecutor.d.ts +42 -2
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +100 -4
- package/src/engine/network/sim/Snapshotter.d.ts +12 -0
- package/src/engine/network/sim/Snapshotter.d.ts.map +1 -1
- package/src/engine/network/sim/Snapshotter.js +43 -0
- package/src/engine/network/state/Baseline.d.ts +1 -1
- package/src/engine/network/state/Baseline.js +1 -1
- package/src/engine/network/state/FrameBufferRing.d.ts +25 -6
- package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -1
- package/src/engine/network/state/FrameBufferRing.js +51 -6
- package/src/engine/network/state/InputRing.d.ts +4 -0
- package/src/engine/network/state/InputRing.d.ts.map +1 -1
- package/src/engine/network/state/InputRing.js +7 -0
- package/src/engine/network/transport/DeferredTransport.d.ts.map +1 -1
- package/src/engine/network/transport/DeferredTransport.js +1 -0
- package/src/engine/network/transport/LoopbackTransport.d.ts.map +1 -1
- package/src/engine/network/transport/LoopbackTransport.js +4 -2
- package/src/engine/network/transport/Transport.d.ts +7 -0
- package/src/engine/network/transport/Transport.d.ts.map +1 -1
- package/src/engine/network/transport/Transport.js +8 -0
- package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/NodeUDPTransport.js +20 -5
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +8 -0
- package/src/engine/network/transport/adapters/WebTransportTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebTransportTransport.js +6 -0
- package/src/engine/network/transport/connection/Connection.d.ts +191 -0
- package/src/engine/network/transport/connection/Connection.d.ts.map +1 -0
- package/src/engine/network/transport/connection/Connection.js +1262 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts +94 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RangeSet.js +260 -0
- package/src/engine/network/transport/connection/RxStream.d.ts +48 -0
- package/src/engine/network/transport/connection/RxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RxStream.js +211 -0
- package/src/engine/network/transport/connection/TxStream.d.ts +90 -0
- package/src/engine/network/transport/connection/TxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/TxStream.js +243 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts +17 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts.map +1 -0
- package/src/engine/network/transport/connection/bytes_copy.js +34 -0
- package/src/engine/network/transport/connection/varint.d.ts +46 -0
- package/src/engine/network/transport/connection/varint.d.ts.map +1 -0
- package/src/engine/network/transport/connection/varint.js +107 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts +38 -7
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitter.js +35 -7
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.js +48 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts +12 -2
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.js +173 -9
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts +9 -3
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/LiveEmitterSet.js +28 -8
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts +8 -0
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.js +51 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.js +15 -1
- package/src/engine/sound/sopra/README.md +768 -644
- package/src/engine/sound/sopra/SopraEngine.d.ts +104 -8
- package/src/engine/sound/sopra/SopraEngine.d.ts.map +1 -1
- package/src/engine/sound/sopra/SopraEngine.js +327 -12
- package/src/engine/sound/sopra/definition/EventDescription.d.ts +28 -2
- package/src/engine/sound/sopra/definition/EventDescription.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescription.js +55 -5
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts +10 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +77 -55
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts +31 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.js +75 -0
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts +38 -9
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +34 -5
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts +7 -2
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +137 -122
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts +3 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.js +146 -131
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts +1 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +6 -1
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts +44 -2
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/BusGraph.js +83 -43
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts +96 -0
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectChain.js +286 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts +123 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.js +320 -0
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts +55 -5
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/EventInstance.js +201 -26
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts +2 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +6 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts +15 -0
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +32 -0
- package/src/engine/sound/sopra/util/MockAudioContext.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/MockAudioContext.js +3 -0
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts +13 -3
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/fadeOutAndStop.js +25 -13
- package/src/shade/RENDERER_CONTRACT.md +6 -3
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts +24 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts.map +1 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.js +34 -0
- package/src/shade/device/ShadeDeviceFailure.d.ts +12 -5
- package/src/shade/device/ShadeDeviceFailure.d.ts.map +1 -1
- package/src/shade/device/ShadeDeviceFailure.js +17 -8
- package/src/shade/device/ShadeDeviceFailureReason.d.ts +1 -1
- package/src/shade/device/ShadeDeviceFailureReason.js +2 -2
- package/src/shade/device/shade_device_floor_unmet.d.ts +13 -0
- package/src/shade/device/shade_device_floor_unmet.d.ts.map +1 -0
- package/src/shade/device/shade_device_floor_unmet.js +32 -0
- package/src/shade/renderer/Renderer.d.ts +2 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +29 -55
- package/src/shade/renderer/buffer/GPUBufferAllocator.d.ts.map +1 -1
- package/src/shade/renderer/buffer/GPUBufferAllocator.js +9 -0
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts +21 -12
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts.map +1 -1
- package/src/shade/renderer/buffer/buffer_pool_ops.js +18 -19
- package/src/shade/renderer/gpu_primitive/test/gpu_test.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/test/gpu_test.js +8 -11
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/pool/TransientResourcePool.d.ts +24 -0
- package/src/shade/renderer/pool/TransientResourcePool.d.ts.map +1 -1
- package/src/shade/renderer/pool/TransientResourcePool.js +41 -10
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +18 -2
- package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ImageShader.js +230 -218
- package/src/view/graphics/GraphicsContextFailureView.d.ts +1 -2
- package/src/view/graphics/GraphicsContextFailureView.d.ts.map +1 -1
- package/src/view/graphics/GraphicsContextFailureView.js +1 -2
- package/src/engine/network/transport/Channel.js +0 -336
- package/src/engine/network/transport/ReliableCommandPipeline.js +0 -335
- package/src/engine/network/transport/fragments/FragmentAssembler.js +0 -350
- package/src/engine/network/transport/fragments/FragmentRetention.js +0 -191
- package/src/engine/network/transport/fragments/fragment_send.js +0 -157
- package/src/engine/network/transport/fragments/packet_size.js +0 -107
|
@@ -45,11 +45,12 @@ export class SopraEngine {
|
|
|
45
45
|
*/
|
|
46
46
|
voiceManager: VoiceManager;
|
|
47
47
|
/**
|
|
48
|
-
* Listener world position for spatialization/attenuation. Null = no listener set yet
|
|
49
|
-
* unattenuated).
|
|
50
|
-
*
|
|
48
|
+
* Listener world position for spatialization/attenuation, read by index. Null = no listener set yet
|
|
49
|
+
* (events play unattenuated). Set it with {@link setListener}, which is also how a move is reported;
|
|
50
|
+
* the ECS `AudioEmitterSystem` drives it from the `SoundListener` entity's transform.
|
|
51
|
+
* @type {ArrayLike<number>|null}
|
|
51
52
|
*/
|
|
52
|
-
listenerPosition:
|
|
53
|
+
listenerPosition: ArrayLike<number> | null;
|
|
53
54
|
/**
|
|
54
55
|
* @type {BaseAudioContext}
|
|
55
56
|
*/
|
|
@@ -88,9 +89,22 @@ export class SopraEngine {
|
|
|
88
89
|
* feeding the old graph, so anything already playing is silenced by the swap rather than
|
|
89
90
|
* re-routed. Swap between scenes, or stop what is playing first.
|
|
90
91
|
*
|
|
92
|
+
* Every bus is built at its DEFINED gain, so by default a fader moved since — a player's volume
|
|
93
|
+
* setting, a bound parameter, a snapshot — is reset by the swap. That is right when the new tree IS
|
|
94
|
+
* the new mix (loading a scene's authored mix). When the tree changes but the mix should not —
|
|
95
|
+
* adding a bus to the tree the player has been adjusting — pass `keepVolumes`: each bus present in
|
|
96
|
+
* both trees keeps its fader where it was, moved the way {@link setBusVolume} moves it (an engaged
|
|
97
|
+
* duck on it carries over too), and buses new to the tree start at their defined gain. Only the
|
|
98
|
+
* faders carry: insert-effect parameters start from the new definitions, which may describe
|
|
99
|
+
* different effects — except one a {@link bindParameterToBusEffectParam} binding holds, which the new
|
|
100
|
+
* tree is built at the bound value of, with `keepVolumes` or without.
|
|
101
|
+
*
|
|
91
102
|
* @param {BusDefinition[]} busDefinitions
|
|
103
|
+
* @param {{keepVolumes?: boolean}} [options]
|
|
92
104
|
*/
|
|
93
|
-
setBuses(busDefinitions: BusDefinition[]
|
|
105
|
+
setBuses(busDefinitions: BusDefinition[], { keepVolumes }?: {
|
|
106
|
+
keepVolumes?: boolean;
|
|
107
|
+
}): void;
|
|
94
108
|
/**
|
|
95
109
|
* Create (but do not start) an instance of an event.
|
|
96
110
|
* @param {EventDescription} description
|
|
@@ -159,10 +173,18 @@ export class SopraEngine {
|
|
|
159
173
|
*/
|
|
160
174
|
getParameter(name: string): number | undefined;
|
|
161
175
|
/**
|
|
162
|
-
* Set the listener world position used for 3D attenuation/culling
|
|
163
|
-
* @
|
|
176
|
+
* Set the listener world position used for 3D attenuation/culling, and report that it moved: every 3D
|
|
177
|
+
* instance re-attenuates against it on the next {@link update}, and none does again until the next
|
|
178
|
+
* call. Held by reference, so after writing into the same array, call this again with it.
|
|
179
|
+
* @param {ArrayLike<number>|null} position read by index
|
|
180
|
+
*/
|
|
181
|
+
setListener(position: ArrayLike<number> | null): void;
|
|
182
|
+
/**
|
|
183
|
+
* Advanced by each {@link setListener}: what a 3D instance compares to tell whether the listener has
|
|
184
|
+
* moved since it last attenuated.
|
|
185
|
+
* @returns {number}
|
|
164
186
|
*/
|
|
165
|
-
|
|
187
|
+
get listenerVersion(): number;
|
|
166
188
|
/**
|
|
167
189
|
* Register a parameter with a default value.
|
|
168
190
|
* @param {string} name
|
|
@@ -182,6 +204,42 @@ export class SopraEngine {
|
|
|
182
204
|
* @param {AnimationCurve} curve maps parameter value -> linear bus gain
|
|
183
205
|
*/
|
|
184
206
|
bindParameterToBusVolume(name: string, busId: string, curve: AnimationCurve): void;
|
|
207
|
+
/**
|
|
208
|
+
* Drive a parameter of one of a bus's insert effects from a sopra parameter through an
|
|
209
|
+
* {@link AnimationCurve} — the effect's counterpart of {@link bindParameterToBusVolume}. A game sets
|
|
210
|
+
* one value (`health`); how far the world's lowpass closes for it is authored in the curve, not
|
|
211
|
+
* worked out in game code.
|
|
212
|
+
*
|
|
213
|
+
* Addressed as {@link setBusEffectParam}, and checked against the tree as it stands: a bus, effect or
|
|
214
|
+
* parameter it does not have throws here, where the binding was written. The parameter's value takes
|
|
215
|
+
* hold at once, without a glide: now if it has one, else when it first gets one.
|
|
216
|
+
*
|
|
217
|
+
* From then on the binding is a standing rule:
|
|
218
|
+
* - each change of the parameter moves the effect — now, or with a `timeConstant` above 0 as a glide
|
|
219
|
+
* ({@link approachBusEffectParam}), so a value set every frame is tracked smoothly;
|
|
220
|
+
* - every tree {@link setBuses} builds that has the target starts at the bound value, not at the
|
|
221
|
+
* definition it was rebuilt from;
|
|
222
|
+
* - over a tree without the target it does nothing, and holds again over the next tree that has it.
|
|
223
|
+
* (A binding cannot be removed, so it has to outlive a tree swap; a mistyped address is caught at
|
|
224
|
+
* the bind.)
|
|
225
|
+
*
|
|
226
|
+
* One binding per parameter and target: binding the same pair again replaces its curve and time
|
|
227
|
+
* constant, and moves the effect to the new curve as a change would — it adds nothing, so binding again
|
|
228
|
+
* after a {@link setBuses} that keeps the target is harmless. Two parameters bound to one target
|
|
229
|
+
* take turns — the last to change wins, and after a rebuild the later binding (a re-bind keeps its
|
|
230
|
+
* place). A direct {@link setBusEffectParam} on a bound effect holds until the parameter next changes.
|
|
231
|
+
*
|
|
232
|
+
* The address is positional, like every effect address: reorder a bus's `effects` and the binding
|
|
233
|
+
* follows whatever now sits at its index.
|
|
234
|
+
*
|
|
235
|
+
* @param {string} name sopra parameter, as {@link setParameter} sets it
|
|
236
|
+
* @param {string} busId
|
|
237
|
+
* @param {number} effectIndex position in the bus definition's `effects`
|
|
238
|
+
* @param {string} paramName one of that effect class's `parameters` (`'frequency'` on an `EqEffect`)
|
|
239
|
+
* @param {AnimationCurve} curve maps the parameter's value to the effect parameter's, in its own units
|
|
240
|
+
* @param {number} [timeConstant=0] seconds: 0 moves the effect now on each change; above 0 glides
|
|
241
|
+
*/
|
|
242
|
+
bindParameterToBusEffectParam(name: string, busId: string, effectIndex: number, paramName: string, curve: AnimationCurve, timeConstant?: number): void;
|
|
185
243
|
/**
|
|
186
244
|
* @param {string} busId
|
|
187
245
|
* @returns {number} linear gain
|
|
@@ -192,6 +250,44 @@ export class SopraEngine {
|
|
|
192
250
|
* @param {number} linear linear gain
|
|
193
251
|
*/
|
|
194
252
|
setBusVolume(busId: string, linear: number): void;
|
|
253
|
+
/**
|
|
254
|
+
* Move a parameter of one of a bus's insert effects ({@link BusDefinition.effects}), now.
|
|
255
|
+
*
|
|
256
|
+
* The effect is addressed by its position in the bus definition's `effects`, the parameter by one of
|
|
257
|
+
* its class's `parameters` — the name of the definition field it starts from (`'frequency'` on an
|
|
258
|
+
* `EqEffect`). It moves the bus's built copy only; the definition is never touched, and
|
|
259
|
+
* {@link setBuses} rebuilds from it. Whatever automation was in flight on the parameter is cancelled.
|
|
260
|
+
*
|
|
261
|
+
* @param {string} busId
|
|
262
|
+
* @param {number} effectIndex
|
|
263
|
+
* @param {string} name
|
|
264
|
+
* @param {number} value in the parameter's own units (Hz, dB, seconds, ...)
|
|
265
|
+
*/
|
|
266
|
+
setBusEffectParam(busId: string, effectIndex: number, name: string, value: number): void;
|
|
267
|
+
/**
|
|
268
|
+
* Glide a parameter of one of a bus's insert effects toward `value` — a lowpass closing over the
|
|
269
|
+
* world as health runs out, a compressor's threshold riding a game state. Exponential, covering ~63%
|
|
270
|
+
* of the way per `timeConstant`, like the fader's ducking glide. Whatever was in flight is cancelled
|
|
271
|
+
* and held first, so a value sent every frame retargets from wherever the last glide had got to.
|
|
272
|
+
*
|
|
273
|
+
* Addressed as {@link setBusEffectParam}.
|
|
274
|
+
*
|
|
275
|
+
* @param {string} busId
|
|
276
|
+
* @param {number} effectIndex
|
|
277
|
+
* @param {string} name
|
|
278
|
+
* @param {number} value
|
|
279
|
+
* @param {number} timeConstant seconds, above 0
|
|
280
|
+
*/
|
|
281
|
+
approachBusEffectParam(busId: string, effectIndex: number, name: string, value: number, timeConstant: number): void;
|
|
282
|
+
/**
|
|
283
|
+
* Where a bus effect's parameter was last sent (the target of a glide still in flight), or its
|
|
284
|
+
* defined value if it has not been moved.
|
|
285
|
+
* @param {string} busId
|
|
286
|
+
* @param {number} effectIndex
|
|
287
|
+
* @param {string} name
|
|
288
|
+
* @returns {number}
|
|
289
|
+
*/
|
|
290
|
+
getBusEffectParam(busId: string, effectIndex: number, name: string): number;
|
|
195
291
|
/**
|
|
196
292
|
* Apply a {@link MixerSnapshot}: move each listed bus to its target gain. `duration` 0 snaps
|
|
197
293
|
* instantly; > 0 click-safely ramps (a mix-state blend).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SopraEngine.d.ts","sourceRoot":"","sources":["../../../../../src/engine/sound/sopra/SopraEngine.js"],"names":[],"mappings":";;;;8BAsBU,MAAM;;;;;;;AAahB;;;;;;;GAOG;AACH;
|
|
1
|
+
{"version":3,"file":"SopraEngine.d.ts","sourceRoot":"","sources":["../../../../../src/engine/sound/sopra/SopraEngine.js"],"names":[],"mappings":"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"}
|
|
@@ -62,23 +62,54 @@ export class SopraEngine {
|
|
|
62
62
|
voiceManager = new VoiceManager();
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
|
-
* Listener world position for spatialization/attenuation. Null = no listener set yet
|
|
66
|
-
* unattenuated).
|
|
67
|
-
*
|
|
65
|
+
* Listener world position for spatialization/attenuation, read by index. Null = no listener set yet
|
|
66
|
+
* (events play unattenuated). Set it with {@link setListener}, which is also how a move is reported;
|
|
67
|
+
* the ECS `AudioEmitterSystem` drives it from the `SoundListener` entity's transform.
|
|
68
|
+
* @type {ArrayLike<number>|null}
|
|
68
69
|
*/
|
|
69
70
|
listenerPosition = null;
|
|
70
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Advanced by every {@link setListener}. An instance re-attenuates when this differs from the value it
|
|
74
|
+
* last attenuated against, so between listener moves nothing is recomputed.
|
|
75
|
+
* @type {number}
|
|
76
|
+
*/
|
|
77
|
+
#listenerVersion = 0;
|
|
78
|
+
|
|
71
79
|
/**
|
|
72
80
|
* @type {Set<EventInstance>}
|
|
73
81
|
*/
|
|
74
82
|
#activeInstances = new Set();
|
|
75
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Where {@link update} takes its snapshot of {@link #activeInstances}, kept rather than built each
|
|
86
|
+
* frame. Emptied after each update so it holds no instance past it.
|
|
87
|
+
* @type {EventInstance[]}
|
|
88
|
+
*/
|
|
89
|
+
#updateSnapshot = [];
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Whether an {@link update} is under way. An update reached from inside one — an instance's end
|
|
93
|
+
* handler ticking the engine — takes a snapshot of its own rather than overwrite the outer one.
|
|
94
|
+
* @type {boolean}
|
|
95
|
+
*/
|
|
96
|
+
#updating = false;
|
|
97
|
+
|
|
76
98
|
/**
|
|
77
99
|
* Active ducking rules + their runtime state.
|
|
78
100
|
* @type {{rule: DuckingRule, engaged: boolean, nominalDb: number}[]}
|
|
79
101
|
*/
|
|
80
102
|
#duckers = [];
|
|
81
103
|
|
|
104
|
+
/**
|
|
105
|
+
* The standing rules of {@link bindParameterToBusEffectParam}, kept so {@link setBuses} can put each
|
|
106
|
+
* one back over the tree it builds.
|
|
107
|
+
* `held`: the binding has put its target at a bound value at least once — until then a value takes
|
|
108
|
+
* hold at once, after that a change glides (with a `timeConstant`).
|
|
109
|
+
* @type {{name: string, busId: string, effectIndex: number, paramName: string, curve: AnimationCurve, timeConstant: number, held: boolean}[]}
|
|
110
|
+
*/
|
|
111
|
+
#effectBindings = [];
|
|
112
|
+
|
|
82
113
|
/**
|
|
83
114
|
* @param {BaseAudioContext} audioContext
|
|
84
115
|
* @param {AudioNode} destinationNode master destination the bus root routes into
|
|
@@ -152,13 +183,48 @@ export class SopraEngine {
|
|
|
152
183
|
* feeding the old graph, so anything already playing is silenced by the swap rather than
|
|
153
184
|
* re-routed. Swap between scenes, or stop what is playing first.
|
|
154
185
|
*
|
|
186
|
+
* Every bus is built at its DEFINED gain, so by default a fader moved since — a player's volume
|
|
187
|
+
* setting, a bound parameter, a snapshot — is reset by the swap. That is right when the new tree IS
|
|
188
|
+
* the new mix (loading a scene's authored mix). When the tree changes but the mix should not —
|
|
189
|
+
* adding a bus to the tree the player has been adjusting — pass `keepVolumes`: each bus present in
|
|
190
|
+
* both trees keeps its fader where it was, moved the way {@link setBusVolume} moves it (an engaged
|
|
191
|
+
* duck on it carries over too), and buses new to the tree start at their defined gain. Only the
|
|
192
|
+
* faders carry: insert-effect parameters start from the new definitions, which may describe
|
|
193
|
+
* different effects — except one a {@link bindParameterToBusEffectParam} binding holds, which the new
|
|
194
|
+
* tree is built at the bound value of, with `keepVolumes` or without.
|
|
195
|
+
*
|
|
155
196
|
* @param {BusDefinition[]} busDefinitions
|
|
197
|
+
* @param {{keepVolumes?: boolean}} [options]
|
|
156
198
|
*/
|
|
157
|
-
setBuses(busDefinitions) {
|
|
158
|
-
this.busGraph
|
|
199
|
+
setBuses(busDefinitions, { keepVolumes = false } = {}) {
|
|
200
|
+
const previous = this.busGraph;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* fader positions to carry over: id -> linear gain
|
|
204
|
+
* @type {Map<string, number>}
|
|
205
|
+
*/
|
|
206
|
+
const kept = new Map();
|
|
207
|
+
|
|
208
|
+
if (keepVolumes) {
|
|
209
|
+
for (const [id, bus] of previous.buses) {
|
|
210
|
+
kept.set(id, bus.nominal);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
previous.dispose();
|
|
159
215
|
|
|
160
216
|
this.busGraph = new BusGraph(this.audioContext, this.destination);
|
|
161
217
|
this.busGraph.build(busDefinitions);
|
|
218
|
+
|
|
219
|
+
for (const [id, linear] of kept) {
|
|
220
|
+
if (this.busGraph.has(id)) {
|
|
221
|
+
this.setBusVolume(id, linear);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// a binding is a standing rule, not a move made once: the rebuilt effect is put at the bound value
|
|
226
|
+
// at once, where it would otherwise sit at its definition until the parameter next changed
|
|
227
|
+
this.#reassertEffectBindings(null);
|
|
162
228
|
}
|
|
163
229
|
|
|
164
230
|
/**
|
|
@@ -265,11 +331,23 @@ export class SopraEngine {
|
|
|
265
331
|
}
|
|
266
332
|
|
|
267
333
|
/**
|
|
268
|
-
* Set the listener world position used for 3D attenuation/culling
|
|
269
|
-
* @
|
|
334
|
+
* Set the listener world position used for 3D attenuation/culling, and report that it moved: every 3D
|
|
335
|
+
* instance re-attenuates against it on the next {@link update}, and none does again until the next
|
|
336
|
+
* call. Held by reference, so after writing into the same array, call this again with it.
|
|
337
|
+
* @param {ArrayLike<number>|null} position read by index
|
|
270
338
|
*/
|
|
271
339
|
setListener(position) {
|
|
272
340
|
this.listenerPosition = position;
|
|
341
|
+
this.#listenerVersion++;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Advanced by each {@link setListener}: what a 3D instance compares to tell whether the listener has
|
|
346
|
+
* moved since it last attenuated.
|
|
347
|
+
* @returns {number}
|
|
348
|
+
*/
|
|
349
|
+
get listenerVersion() {
|
|
350
|
+
return this.#listenerVersion;
|
|
273
351
|
}
|
|
274
352
|
|
|
275
353
|
/**
|
|
@@ -278,7 +356,15 @@ export class SopraEngine {
|
|
|
278
356
|
* @param {number} [defaultValue]
|
|
279
357
|
*/
|
|
280
358
|
defineParameter(name, defaultValue = 0) {
|
|
359
|
+
const fresh = !this.parameters.has(name);
|
|
360
|
+
|
|
281
361
|
this.parameters.define(name, defaultValue);
|
|
362
|
+
|
|
363
|
+
// `define` runs no binding, and a later `set` to the same value is no change, so an effect bound
|
|
364
|
+
// before its parameter existed would otherwise wait for a different value - or the next setBuses
|
|
365
|
+
if (fresh) {
|
|
366
|
+
this.#reassertEffectBindings(name);
|
|
367
|
+
}
|
|
282
368
|
}
|
|
283
369
|
|
|
284
370
|
/**
|
|
@@ -300,6 +386,169 @@ export class SopraEngine {
|
|
|
300
386
|
this.parameters.bind(name, (value) => this.setBusVolume(busId, curve.evaluate(value)));
|
|
301
387
|
}
|
|
302
388
|
|
|
389
|
+
/**
|
|
390
|
+
* Drive a parameter of one of a bus's insert effects from a sopra parameter through an
|
|
391
|
+
* {@link AnimationCurve} — the effect's counterpart of {@link bindParameterToBusVolume}. A game sets
|
|
392
|
+
* one value (`health`); how far the world's lowpass closes for it is authored in the curve, not
|
|
393
|
+
* worked out in game code.
|
|
394
|
+
*
|
|
395
|
+
* Addressed as {@link setBusEffectParam}, and checked against the tree as it stands: a bus, effect or
|
|
396
|
+
* parameter it does not have throws here, where the binding was written. The parameter's value takes
|
|
397
|
+
* hold at once, without a glide: now if it has one, else when it first gets one.
|
|
398
|
+
*
|
|
399
|
+
* From then on the binding is a standing rule:
|
|
400
|
+
* - each change of the parameter moves the effect — now, or with a `timeConstant` above 0 as a glide
|
|
401
|
+
* ({@link approachBusEffectParam}), so a value set every frame is tracked smoothly;
|
|
402
|
+
* - every tree {@link setBuses} builds that has the target starts at the bound value, not at the
|
|
403
|
+
* definition it was rebuilt from;
|
|
404
|
+
* - over a tree without the target it does nothing, and holds again over the next tree that has it.
|
|
405
|
+
* (A binding cannot be removed, so it has to outlive a tree swap; a mistyped address is caught at
|
|
406
|
+
* the bind.)
|
|
407
|
+
*
|
|
408
|
+
* One binding per parameter and target: binding the same pair again replaces its curve and time
|
|
409
|
+
* constant, and moves the effect to the new curve as a change would — it adds nothing, so binding again
|
|
410
|
+
* after a {@link setBuses} that keeps the target is harmless. Two parameters bound to one target
|
|
411
|
+
* take turns — the last to change wins, and after a rebuild the later binding (a re-bind keeps its
|
|
412
|
+
* place). A direct {@link setBusEffectParam} on a bound effect holds until the parameter next changes.
|
|
413
|
+
*
|
|
414
|
+
* The address is positional, like every effect address: reorder a bus's `effects` and the binding
|
|
415
|
+
* follows whatever now sits at its index.
|
|
416
|
+
*
|
|
417
|
+
* @param {string} name sopra parameter, as {@link setParameter} sets it
|
|
418
|
+
* @param {string} busId
|
|
419
|
+
* @param {number} effectIndex position in the bus definition's `effects`
|
|
420
|
+
* @param {string} paramName one of that effect class's `parameters` (`'frequency'` on an `EqEffect`)
|
|
421
|
+
* @param {AnimationCurve} curve maps the parameter's value to the effect parameter's, in its own units
|
|
422
|
+
* @param {number} [timeConstant=0] seconds: 0 moves the effect now on each change; above 0 glides
|
|
423
|
+
*/
|
|
424
|
+
bindParameterToBusEffectParam(name, busId, effectIndex, paramName, curve, timeConstant = 0) {
|
|
425
|
+
assert.isString(name, 'name');
|
|
426
|
+
assert.defined(curve, 'curve');
|
|
427
|
+
assert.isFinite(timeConstant, 'timeConstant');
|
|
428
|
+
assert.greaterThanOrEqual(timeConstant, 0, 'timeConstant');
|
|
429
|
+
|
|
430
|
+
// throws naming what the tree lacks
|
|
431
|
+
this.busGraph.getEffectParam(busId, effectIndex, paramName);
|
|
432
|
+
|
|
433
|
+
const parameters = this.parameters;
|
|
434
|
+
const existing = this.#findEffectBinding(name, busId, effectIndex, paramName);
|
|
435
|
+
const binding = { name, busId, effectIndex, paramName, curve, timeConstant, held: existing !== null && existing.held };
|
|
436
|
+
|
|
437
|
+
// Put the effect at the bound value BEFORE registering or replacing anything, so a curve that cannot
|
|
438
|
+
// be applied leaves no half-made binding behind. A new binding takes hold as a move, not a glide - it
|
|
439
|
+
// does not sweep in from wherever the definition left the effect; one replacing a binding that
|
|
440
|
+
// already holds the effect moves it the way a change would.
|
|
441
|
+
if (parameters.has(name)) {
|
|
442
|
+
this.#applyEffectBinding(binding, parameters.get(name), binding.held ? timeConstant : 0);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (existing !== null) {
|
|
446
|
+
// the store already calls the one callback this pair has, and it reads the record
|
|
447
|
+
existing.curve = curve;
|
|
448
|
+
existing.timeConstant = timeConstant;
|
|
449
|
+
existing.held = binding.held;
|
|
450
|
+
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
this.#effectBindings.push(binding);
|
|
455
|
+
|
|
456
|
+
// the store calls a callback once as it is bound, when the parameter has a value; that one is
|
|
457
|
+
// already applied above
|
|
458
|
+
let bound = false;
|
|
459
|
+
|
|
460
|
+
parameters.bind(name, (value) => {
|
|
461
|
+
if (bound) {
|
|
462
|
+
// a parameter's first value takes hold; only a change after that is a glide
|
|
463
|
+
this.#applyEffectBinding(binding, value, binding.held ? binding.timeConstant : 0);
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
bound = true;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* @param {string} name
|
|
472
|
+
* @param {string} busId
|
|
473
|
+
* @param {number} effectIndex
|
|
474
|
+
* @param {string} paramName
|
|
475
|
+
* @returns {{name: string, busId: string, effectIndex: number, paramName: string, curve: AnimationCurve, timeConstant: number, held: boolean}|null}
|
|
476
|
+
*/
|
|
477
|
+
#findEffectBinding(name, busId, effectIndex, paramName) {
|
|
478
|
+
const bindings = this.#effectBindings;
|
|
479
|
+
|
|
480
|
+
for (let i = 0; i < bindings.length; i++) {
|
|
481
|
+
const b = bindings[i];
|
|
482
|
+
|
|
483
|
+
if (b.name === name && b.busId === busId && b.effectIndex === effectIndex && b.paramName === paramName) {
|
|
484
|
+
return b;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return null;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Put every effect binding — or only those of parameter `name` — at its bound value now, over the
|
|
493
|
+
* current tree. Each is tried: one whose curve cannot be applied (a stored value it cannot evaluate)
|
|
494
|
+
* does not keep the rest from holding, and the first such failure is thrown once they all have.
|
|
495
|
+
* @param {string|null} name null: every binding
|
|
496
|
+
*/
|
|
497
|
+
#reassertEffectBindings(name) {
|
|
498
|
+
const bindings = this.#effectBindings;
|
|
499
|
+
const parameters = this.parameters;
|
|
500
|
+
|
|
501
|
+
let failure = null;
|
|
502
|
+
|
|
503
|
+
for (let i = 0; i < bindings.length; i++) {
|
|
504
|
+
const binding = bindings[i];
|
|
505
|
+
|
|
506
|
+
if ((name !== null && binding.name !== name) || !parameters.has(binding.name)) {
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
try {
|
|
511
|
+
this.#applyEffectBinding(binding, parameters.get(binding.name), 0);
|
|
512
|
+
} catch (e) {
|
|
513
|
+
if (failure === null) {
|
|
514
|
+
failure = e;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (failure !== null) {
|
|
520
|
+
throw failure;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Put one effect binding's target at the curve's value for `value`, over the current tree — if it has
|
|
526
|
+
* that target at all (see {@link bindParameterToBusEffectParam}).
|
|
527
|
+
* @param {{busId: string, effectIndex: number, paramName: string, curve: AnimationCurve, held: boolean}} binding
|
|
528
|
+
* @param {number} value the sopra parameter's
|
|
529
|
+
* @param {number} timeConstant 0 moves it now; above 0 glides
|
|
530
|
+
*/
|
|
531
|
+
#applyEffectBinding(binding, value, timeConstant) {
|
|
532
|
+
const graph = this.busGraph;
|
|
533
|
+
const busId = binding.busId;
|
|
534
|
+
const effectIndex = binding.effectIndex;
|
|
535
|
+
const paramName = binding.paramName;
|
|
536
|
+
|
|
537
|
+
if (!graph.hasEffectParam(busId, effectIndex, paramName)) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
const target = binding.curve.evaluate(value);
|
|
542
|
+
|
|
543
|
+
if (timeConstant > 0) {
|
|
544
|
+
graph.approachEffectParam(busId, effectIndex, paramName, target, timeConstant);
|
|
545
|
+
} else {
|
|
546
|
+
graph.setEffectParam(busId, effectIndex, paramName, target);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
binding.held = true;
|
|
550
|
+
}
|
|
551
|
+
|
|
303
552
|
/**
|
|
304
553
|
* @param {string} busId
|
|
305
554
|
* @returns {number} linear gain
|
|
@@ -318,6 +567,53 @@ export class SopraEngine {
|
|
|
318
567
|
this.#reduck(busId);
|
|
319
568
|
}
|
|
320
569
|
|
|
570
|
+
/**
|
|
571
|
+
* Move a parameter of one of a bus's insert effects ({@link BusDefinition.effects}), now.
|
|
572
|
+
*
|
|
573
|
+
* The effect is addressed by its position in the bus definition's `effects`, the parameter by one of
|
|
574
|
+
* its class's `parameters` — the name of the definition field it starts from (`'frequency'` on an
|
|
575
|
+
* `EqEffect`). It moves the bus's built copy only; the definition is never touched, and
|
|
576
|
+
* {@link setBuses} rebuilds from it. Whatever automation was in flight on the parameter is cancelled.
|
|
577
|
+
*
|
|
578
|
+
* @param {string} busId
|
|
579
|
+
* @param {number} effectIndex
|
|
580
|
+
* @param {string} name
|
|
581
|
+
* @param {number} value in the parameter's own units (Hz, dB, seconds, ...)
|
|
582
|
+
*/
|
|
583
|
+
setBusEffectParam(busId, effectIndex, name, value) {
|
|
584
|
+
this.busGraph.setEffectParam(busId, effectIndex, name, value);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Glide a parameter of one of a bus's insert effects toward `value` — a lowpass closing over the
|
|
589
|
+
* world as health runs out, a compressor's threshold riding a game state. Exponential, covering ~63%
|
|
590
|
+
* of the way per `timeConstant`, like the fader's ducking glide. Whatever was in flight is cancelled
|
|
591
|
+
* and held first, so a value sent every frame retargets from wherever the last glide had got to.
|
|
592
|
+
*
|
|
593
|
+
* Addressed as {@link setBusEffectParam}.
|
|
594
|
+
*
|
|
595
|
+
* @param {string} busId
|
|
596
|
+
* @param {number} effectIndex
|
|
597
|
+
* @param {string} name
|
|
598
|
+
* @param {number} value
|
|
599
|
+
* @param {number} timeConstant seconds, above 0
|
|
600
|
+
*/
|
|
601
|
+
approachBusEffectParam(busId, effectIndex, name, value, timeConstant) {
|
|
602
|
+
this.busGraph.approachEffectParam(busId, effectIndex, name, value, timeConstant);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Where a bus effect's parameter was last sent (the target of a glide still in flight), or its
|
|
607
|
+
* defined value if it has not been moved.
|
|
608
|
+
* @param {string} busId
|
|
609
|
+
* @param {number} effectIndex
|
|
610
|
+
* @param {string} name
|
|
611
|
+
* @returns {number}
|
|
612
|
+
*/
|
|
613
|
+
getBusEffectParam(busId, effectIndex, name) {
|
|
614
|
+
return this.busGraph.getEffectParam(busId, effectIndex, name);
|
|
615
|
+
}
|
|
616
|
+
|
|
321
617
|
/**
|
|
322
618
|
* Apply a {@link MixerSnapshot}: move each listed bus to its target gain. `duration` 0 snaps
|
|
323
619
|
* instantly; > 0 click-safely ramps (a mix-state blend).
|
|
@@ -362,13 +658,32 @@ export class SopraEngine {
|
|
|
362
658
|
* @param {number} [now] context time; defaults to the live clock
|
|
363
659
|
*/
|
|
364
660
|
update(now = this.currentTime) {
|
|
365
|
-
|
|
661
|
+
/*
|
|
662
|
+
Snapshot: an instance may finish (and remove itself) during its own update, and one played from
|
|
663
|
+
inside an update waits for the next. Written by index into a kept array up to a count, and
|
|
664
|
+
nulled after, rather than emptied with `length = 0`, which lets V8 trim the store it would only
|
|
665
|
+
grow back on the next frame.
|
|
666
|
+
*/
|
|
667
|
+
const nested = this.#updating;
|
|
668
|
+
const instances = nested ? [] : this.#updateSnapshot;
|
|
669
|
+
|
|
670
|
+
let count = 0;
|
|
671
|
+
|
|
672
|
+
for (const instance of this.#activeInstances) {
|
|
673
|
+
instances[count++] = instance;
|
|
674
|
+
}
|
|
366
675
|
|
|
367
|
-
|
|
368
|
-
|
|
676
|
+
this.#updating = true;
|
|
677
|
+
|
|
678
|
+
try {
|
|
679
|
+
for (let i = 0; i < count; i++) {
|
|
680
|
+
// each reads the listener itself, with the version that goes with it
|
|
681
|
+
instances[i].update(now);
|
|
682
|
+
}
|
|
683
|
+
} finally {
|
|
684
|
+
this.#updating = nested;
|
|
369
685
|
|
|
370
|
-
|
|
371
|
-
instances[i].update(now, listenerPosition);
|
|
686
|
+
instances.fill(null, 0, count);
|
|
372
687
|
}
|
|
373
688
|
|
|
374
689
|
this.#updateDuckers();
|
|
@@ -11,7 +11,7 @@ export class EventDescription {
|
|
|
11
11
|
* @param {Partial<EventDescription>} [options]
|
|
12
12
|
* @returns {EventDescription}
|
|
13
13
|
*/
|
|
14
|
-
static from(label: string, rootClip: AbstractAudioClip, { busId, gainDb, is3D, panningModel, distanceMin, distanceMax, attenuation, maxInstances, priority, stealMode, virtualThresholdDb }?: Partial<EventDescription>): EventDescription;
|
|
14
|
+
static from(label: string, rootClip: AbstractAudioClip, { busId, gainDb, is3D, panningModel, distanceMin, distanceMax, attenuation, maxInstances, priority, stealMode, virtualThresholdDb, effects }?: Partial<EventDescription>): EventDescription;
|
|
15
15
|
/**
|
|
16
16
|
* Human-readable label (need not be unique).
|
|
17
17
|
* @type {string}
|
|
@@ -76,6 +76,21 @@ export class EventDescription {
|
|
|
76
76
|
* @type {number}
|
|
77
77
|
*/
|
|
78
78
|
virtualThresholdDb: number;
|
|
79
|
+
/**
|
|
80
|
+
* Insert effects every instance of this event plays through, in order — the event's own DSP, as a
|
|
81
|
+
* bus has its own ({@link BusDefinition.effects}). Each instance builds its own copy, ahead of its
|
|
82
|
+
* fader: `voices → effects[0] → … → effects[n] → instance gain → (3D chain) → bus`.
|
|
83
|
+
*
|
|
84
|
+
* Because the copy is per instance, so is its control: one play of an event can be filtered or
|
|
85
|
+
* compressed independently of every other play of it, through {@link EventInstance#setEffectParam}.
|
|
86
|
+
* Empty (the default) builds nothing.
|
|
87
|
+
*
|
|
88
|
+
* Part of {@link equals} and {@link hash}, like every authored field — so never edit an effect's fields
|
|
89
|
+
* in place on a description that is playing: the `VoiceManager` files live instances under the hash, and
|
|
90
|
+
* a moved field loses them. Move a playing effect through its instance.
|
|
91
|
+
* @type {AbstractAudioEffect[]}
|
|
92
|
+
*/
|
|
93
|
+
effects: AbstractAudioEffect[];
|
|
79
94
|
/**
|
|
80
95
|
*
|
|
81
96
|
* @param {EventDescription} other
|
|
@@ -94,6 +109,11 @@ export class EventDescription {
|
|
|
94
109
|
label: string;
|
|
95
110
|
rootClip: {
|
|
96
111
|
type: string;
|
|
112
|
+
/**
|
|
113
|
+
* The triggerable unit (FMOD EventDescription / Wwise Actor-Mixer object). Immutable authored data;
|
|
114
|
+
* playing it spawns a transient {@link EventInstance}. Held as data (e.g. by an `AudioEmitter`) and
|
|
115
|
+
* passed directly to {@link SopraEngine.playEvent} / `playOneShot`.
|
|
116
|
+
*/
|
|
97
117
|
data: any;
|
|
98
118
|
};
|
|
99
119
|
busId: string;
|
|
@@ -109,8 +129,12 @@ export class EventDescription {
|
|
|
109
129
|
priority: number;
|
|
110
130
|
stealMode: number;
|
|
111
131
|
virtualThresholdDb: number;
|
|
132
|
+
effects: {
|
|
133
|
+
type: string;
|
|
134
|
+
data: any;
|
|
135
|
+
}[];
|
|
112
136
|
};
|
|
113
|
-
fromJSON({ label, rootClip, busId, gainDb, is3D, panningModel, distanceMin, distanceMax, attenuation, maxInstances, priority, stealMode, virtualThresholdDb }: {
|
|
137
|
+
fromJSON({ label, rootClip, busId, gainDb, is3D, panningModel, distanceMin, distanceMax, attenuation, maxInstances, priority, stealMode, virtualThresholdDb, effects }: {
|
|
114
138
|
label?: string;
|
|
115
139
|
rootClip: any;
|
|
116
140
|
busId?: string;
|
|
@@ -124,12 +148,14 @@ export class EventDescription {
|
|
|
124
148
|
priority?: number;
|
|
125
149
|
stealMode?: number;
|
|
126
150
|
virtualThresholdDb?: number;
|
|
151
|
+
effects?: any[];
|
|
127
152
|
}): void;
|
|
128
153
|
}
|
|
129
154
|
export namespace EventDescription {
|
|
130
155
|
let typeName: string;
|
|
131
156
|
}
|
|
132
157
|
export type AbstractAudioClip = import("./clip/AbstractAudioClip.js").AbstractAudioClip;
|
|
158
|
+
export type AbstractAudioEffect = import("./effect/AbstractAudioEffect.js").AbstractAudioEffect;
|
|
133
159
|
import { SopraPanningModel } from "./SopraPanningModel.js";
|
|
134
160
|
import { AnimationCurve } from "../../../animation/curve/AnimationCurve.js";
|
|
135
161
|
import { VoiceStealMode } from "./VoiceStealMode.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventDescription.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/sopra/definition/EventDescription.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EventDescription.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/sopra/definition/EventDescription.js"],"names":[],"mappings":"AA4BA;;;;GAIG;AACH;IA+FI;;;;;;OAMG;IACH,mBALW,MAAM,YACN,iBAAiB,iJACjB,QAAQ,gBAAgB,CAAC,GACvB,gBAAgB,CAkC5B;IApID;;;OAGG;IACH,OAFU,MAAM,CAEL;IAEX;;;OAGG;IACH,UAFU,iBAAiB,CAEO;IAElC;;;OAGG;IACH,OAFU,MAAM,CAEE;IAElB;;;OAGG;IACH,QAFU,MAAM,CAEL;IAEX;;;OAGG;IACH,MAFU,OAAO,CAEJ;IAEb;;;OAGG;IACH,cAFU,iBAAiB,GAAC,MAAM,CAEI;IAEtC;;OAEG;IACH,aAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,aAFU,MAAM,CAEI;IAEpB;;;OAGG;IACH,aAFU,cAAc,CAEW;IAEnC;;;OAGG;IACH,cAFU,MAAM,CAEE;IAElB;;;OAGG;IACH,UAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,WAFU,cAAc,GAAC,MAAM,CAEG;IAElC;;;OAGG;IACH,oBAFU,MAAM,CAES;IAEzB;;;;;;;;;;;;;OAaG;IACH,SAFU,mBAAmB,EAAE,CAElB;IA2Cb;;;;OAIG;IACH,cAHW,gBAAgB,GACd,OAAO,CA4BnB;IAED;;;;;OAKG;IACH,QAFa,MAAM,CAoClB;IAED,0BAmBC;IAED;;;;YA7OJ;;;;eAIG;;;;;;;;;;;;;;;;;;;;MA0PE;IAED;;;;;;;;;;;;;;;aAsCC;CACJ;;;;gCAnTY,OAAO,6BAA6B,EAAE,iBAAiB;kCACvD,OAAO,iCAAiC,EAAE,mBAAmB;kCALxC,wBAAwB;+BAR3B,4CAA4C;+BAS5C,qBAAqB"}
|