@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
|
@@ -5,6 +5,7 @@ import Vector1 from "../../../../core/geom/Vector1.js";
|
|
|
5
5
|
import { computeHashFloat } from "../../../../core/primitives/numbers/computeHashFloat.js";
|
|
6
6
|
import { AcousticDirectivity } from "../../simulation/definition/AcousticDirectivity.js";
|
|
7
7
|
import { EventDescription } from "../../sopra/definition/EventDescription.js";
|
|
8
|
+
import { EffectParamOverrides } from "../../sopra/runtime/EffectParamOverrides.js";
|
|
8
9
|
|
|
9
10
|
const DEFAULT_SOURCE_RADIUS = 0.05;
|
|
10
11
|
|
|
@@ -22,13 +23,14 @@ export class AudioEmitter {
|
|
|
22
23
|
/**
|
|
23
24
|
* The authored event this emitter plays.
|
|
24
25
|
*
|
|
25
|
-
* Authored data: fixed for as long as the emitter is playing. Routing (`busId`,
|
|
26
|
-
* `panningModel`) decides the shape of the instance's audio graph, which is built once when
|
|
27
|
-
* voice starts; and `distanceMin`, `distanceMax`, `maxInstances
|
|
28
|
-
* part in {@link EventDescription.hash}, which
|
|
29
|
-
* editing any of them in place on a sounding emitter
|
|
30
|
-
* longer be found by. Change them by re-linking the
|
|
31
|
-
* the voice down and re-reads the description cleanly.
|
|
26
|
+
* Authored data: fixed for as long as the emitter is linked, playing or dormant. Routing (`busId`,
|
|
27
|
+
* `is3D`, `panningModel`) decides the shape of the instance's audio graph, which is built once when
|
|
28
|
+
* the voice starts; and `distanceMin`, `distanceMax`, `maxInstances`, the attenuation curve and the
|
|
29
|
+
* insert `effects` (every field of every effect) all take part in {@link EventDescription.hash}, which
|
|
30
|
+
* the `VoiceManager` buckets live instances by — so editing any of them in place on a sounding emitter
|
|
31
|
+
* files that instance under a hash it can no longer be found by. Change them by re-linking the
|
|
32
|
+
* component (remove and re-add it), which tears the voice down and re-reads the description cleanly.
|
|
33
|
+
* A playing effect's parameters move through {@link effectOverrides}, never through the definition.
|
|
32
34
|
*
|
|
33
35
|
* @type {EventDescription}
|
|
34
36
|
*/
|
|
@@ -71,6 +73,32 @@ export class AudioEmitter {
|
|
|
71
73
|
*/
|
|
72
74
|
directivity = new AcousticDirectivity();
|
|
73
75
|
|
|
76
|
+
/**
|
|
77
|
+
* This emitter's own values for its event's insert-effect parameters ({@link EventDescription.effects}):
|
|
78
|
+
* a lowpass closing over one torch as a door shuts on it, while every other torch playing the same
|
|
79
|
+
* event stays bright.
|
|
80
|
+
*
|
|
81
|
+
* Live state, the way {@link volume} is live — plumbed by `AudioEmitterSystem` onto whichever instance
|
|
82
|
+
* is current, and put onto every new one. A spatially managed emitter's instance is torn down when it
|
|
83
|
+
* is demoted and built afresh when it is promoted again, and is built at these values, not the event's;
|
|
84
|
+
* a value moved straight on an instance (`AudioEmitterSystem.instanceFor(entity).setEffectParam`) lasts
|
|
85
|
+
* only as long as that instance.
|
|
86
|
+
*
|
|
87
|
+
* Not authored data, so absent from {@link toJSON}, {@link equals} and {@link hash}: two emitters that
|
|
88
|
+
* differ only in where a filter has been turned are the same emitter, and the overrides must change
|
|
89
|
+
* neither what a save contains nor which polyphony bucket a voice is filed under.
|
|
90
|
+
*
|
|
91
|
+
* Checked against the event: while the emitter is linked, an override its event has no such parameter
|
|
92
|
+
* for throws where it is written, and is not kept; one written before the link is checked by the link,
|
|
93
|
+
* which throws instead of playing. So {@link EffectParamOverrides#clear} them before re-adding the
|
|
94
|
+
* component with a different event. One entity per `AudioEmitter`: a second link of the same component
|
|
95
|
+
* throws, since the overrides can follow only one playing instance.
|
|
96
|
+
*
|
|
97
|
+
* @readonly
|
|
98
|
+
* @type {EffectParamOverrides}
|
|
99
|
+
*/
|
|
100
|
+
effectOverrides = new EffectParamOverrides();
|
|
101
|
+
|
|
74
102
|
/**
|
|
75
103
|
* Observation surface, not authored state — deliberately absent from {@link toJSON}, {@link equals}
|
|
76
104
|
* and {@link hash}: two emitters that differ only in who is listening are the same emitter, and a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioEmitterSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js"],"names":[],"mappings":"AAKA;;;;;;;;;;GAUG;AACH;;IACI,2BAAqB;
|
|
1
|
+
{"version":3,"file":"AudioEmitterSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js"],"names":[],"mappings":"AAKA;;;;;;;;;;GAUG;AACH;;IACI,2BAAqB;IAiBrB;;;OAGG;IACH,mFAEC;IAED;;;OAGG;IACH,uCAFW,YAAY,QAWtB;IAED;;;OAGG;IACH,yCAFW,YAAY,QAWtB;;CACJ;gDAvE+C,gEAAgE;6BAGnF,mBAAmB"}
|
|
@@ -16,7 +16,11 @@ import { AudioEmitter } from "./AudioEmitter.js";
|
|
|
16
16
|
*/
|
|
17
17
|
export class AudioEmitterSerializationAdapter extends BinaryClassSerializationAdapter {
|
|
18
18
|
klass = AudioEmitter;
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* 1: the embedded event record moved to its format 1 (insert effects) — `AudioEmitterSerializationUpgrader_0_1`.
|
|
21
|
+
* @type {number}
|
|
22
|
+
*/
|
|
23
|
+
version = 1;
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* @type {EventDescriptionSerializationAdapter}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry} BinarySerializationRegistry
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Version 0 → 1: the embedded {@link EventDescription} record moved to its own format 1 (insert effects).
|
|
6
|
+
* The record leads the component and carries no version tag of its own, so the component's version is what
|
|
7
|
+
* says which layout it is in; every field after it is unchanged.
|
|
8
|
+
*/
|
|
9
|
+
export class AudioEmitterSerializationUpgrader_0_1 extends BinaryClassUpgrader {
|
|
10
|
+
/**
|
|
11
|
+
* @param {BinarySerializationRegistry} registry where the event's clip types are registered
|
|
12
|
+
*/
|
|
13
|
+
constructor(registry: BinarySerializationRegistry);
|
|
14
|
+
#private;
|
|
15
|
+
}
|
|
16
|
+
export type BinarySerializationRegistry = import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry;
|
|
17
|
+
import { BinaryClassUpgrader } from "../../../ecs/storage/binary/BinaryClassUpgrader.js";
|
|
18
|
+
//# sourceMappingURL=AudioEmitterSerializationUpgrader_0_1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioEmitterSerializationUpgrader_0_1.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.js"],"names":[],"mappings":"AAMA;;GAEG;AAEH;;;;GAIG;AACH;IASI;;OAEG;IACH,sBAFW,2BAA2B,EAMrC;;CAgBJ;0CAxCY,OAAO,4DAA4D,EAAE,2BAA2B;oCANzE,oDAAoD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
|
|
2
|
+
import { BinaryClassUpgrader } from "../../../ecs/storage/binary/BinaryClassUpgrader.js";
|
|
3
|
+
import {
|
|
4
|
+
EventDescriptionSerializationUpgrader_0_1
|
|
5
|
+
} from "../../sopra/definition/EventDescriptionSerializationUpgrader_0_1.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry} BinarySerializationRegistry
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Version 0 → 1: the embedded {@link EventDescription} record moved to its own format 1 (insert effects).
|
|
13
|
+
* The record leads the component and carries no version tag of its own, so the component's version is what
|
|
14
|
+
* says which layout it is in; every field after it is unchanged.
|
|
15
|
+
*/
|
|
16
|
+
export class AudioEmitterSerializationUpgrader_0_1 extends BinaryClassUpgrader {
|
|
17
|
+
__startVersion = 0;
|
|
18
|
+
__targetVersion = 1;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @type {EventDescriptionSerializationUpgrader_0_1}
|
|
22
|
+
*/
|
|
23
|
+
#event;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {BinarySerializationRegistry} registry where the event's clip types are registered
|
|
27
|
+
*/
|
|
28
|
+
constructor(registry) {
|
|
29
|
+
super();
|
|
30
|
+
|
|
31
|
+
this.#event = new EventDescriptionSerializationUpgrader_0_1(registry);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {BinaryBuffer} source
|
|
36
|
+
* @param {BinaryBuffer} target
|
|
37
|
+
*/
|
|
38
|
+
upgrade(source, target) {
|
|
39
|
+
this.#event.upgrade(source, target);
|
|
40
|
+
|
|
41
|
+
BinaryBuffer.copyFloat32(source, target); // volume
|
|
42
|
+
BinaryBuffer.copyUint8(source, target); // autoplay
|
|
43
|
+
BinaryBuffer.copyUint8(source, target); // acoustic
|
|
44
|
+
BinaryBuffer.copyFloat32(source, target); // sourceRadius
|
|
45
|
+
BinaryBuffer.copyFloat32(source, target); // directivity.dipoleWeight
|
|
46
|
+
BinaryBuffer.copyFloat32(source, target); // directivity.dipolePower
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Drives {@link AudioEmitter} components through the shared sopra engine. Each emitter owns its
|
|
3
3
|
* {@link EventDescription} directly (no track translation); the entity's {@link Transform64} feeds
|
|
4
|
-
* position; `volume` changes plumb to the instance gain
|
|
4
|
+
* position; `volume` changes plumb to the instance gain, and `effectOverrides` to the instance's effect
|
|
5
|
+
* parameters — both put onto every instance the emitter gets. Each frame it forwards the listener pose,
|
|
5
6
|
* refreshes the spatial live set, and ticks sopra.
|
|
6
7
|
*
|
|
7
8
|
* **Two play paths**, chosen once at {@link link} (routing is fixed for the lifetime of the link —
|
|
@@ -50,7 +51,7 @@ export class AudioEmitterSystem extends System<any> {
|
|
|
50
51
|
*/
|
|
51
52
|
acousticLive: EventInstance[];
|
|
52
53
|
/**
|
|
53
|
-
* Per-entity records: { emitter, transform, managed, instance, onVolume }. For a managed (3D)
|
|
54
|
+
* Per-entity records: { emitter, transform, managed, instance, onVolume, effectOverrides, onEffectOverride, ... }. For a managed (3D)
|
|
54
55
|
* emitter the playing instance lives in {@link liveSet} (record.instance stays null); for a
|
|
55
56
|
* direct (2D) emitter it is held here.
|
|
56
57
|
* @type {object[]}
|
|
@@ -112,6 +113,15 @@ export class AudioEmitterSystem extends System<any> {
|
|
|
112
113
|
* @returns {EventInstance|null}
|
|
113
114
|
*/
|
|
114
115
|
instanceFor(entity: number): EventInstance | null;
|
|
116
|
+
/**
|
|
117
|
+
* @param {EntityComponentDataset} dataset
|
|
118
|
+
*/
|
|
119
|
+
handleDatasetDetached(dataset: EntityComponentDataset): void;
|
|
120
|
+
/**
|
|
121
|
+
* @param {EntityManager} entityManager
|
|
122
|
+
* @returns {Promise<void>}
|
|
123
|
+
*/
|
|
124
|
+
shutdown(entityManager: EntityManager): Promise<void>;
|
|
115
125
|
update(timeDelta: any): void;
|
|
116
126
|
#private;
|
|
117
127
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioEmitterSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSystem.js"],"names":[],"mappings":"AAwBA
|
|
1
|
+
{"version":3,"file":"AudioEmitterSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/AudioEmitterSystem.js"],"names":[],"mappings":"AAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IAgCI;;;;;OAKG;IACH,0FAHW;QAAC,MAAM,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAA;KAAC,qBA+C1E;IAjFD,2DAA2C;IAE3C;;;;;OAKG;IACH,iBAFU,kBAAkB,CAEA;IAE5B;;;OAGG;IACH,cAFU,eAAe,CAEP;IAElB;;;;;OAKG;IACH,MAFU,MAAM,EAAE,CAER;IAEV;;;;OAIG;IACH,aAFU,sBAAoB,IAAI,CAEf;IAWf;;;;;OAKG;IACH,aAFU,oBAAkB,IAAI,CAEF;IAE9B;;OAEG;IACH,yBAA8B;IAE9B;;OAEG;IACH,iBAFU,YAAY,CAEoB;IAE1C;;OAEG;IACH,2BAAgC;IAQhC;;;OAGG;IACH,mBAAkF;IAElF;;;;OAIG;IACH,SAFU,cAAc,CAE4C;IAGxE;;;;OAIG;IACH,cAJW,YAAY,aACZ,WAAW,UACX,MAAM,QAyEhB;IAED;;;;OAIG;IACH,gBAJW,YAAY,aACZ,WAAW,UACX,MAAM,QAkChB;IAED;;;;;;OAMG;IACH,oBAHW,MAAM,GACJ,gBAAc,IAAI,CAe9B;IAoJD;;OAEG;IACH,6DAKC;IAED;;;OAGG;IACH,wCAFa,QAAQ,IAAI,CAAC,CAKzB;IAmBD,6BAoFC;;CACJ;uBA3hBsB,wBAAwB;4BAGnB,uCAAuC;6BAKtC,mBAAmB;+BACjB,qBAAqB"}
|
|
@@ -25,7 +25,8 @@ const LISTENER_ROTATION = new Quaternion();
|
|
|
25
25
|
/**
|
|
26
26
|
* Drives {@link AudioEmitter} components through the shared sopra engine. Each emitter owns its
|
|
27
27
|
* {@link EventDescription} directly (no track translation); the entity's {@link Transform64} feeds
|
|
28
|
-
* position; `volume` changes plumb to the instance gain
|
|
28
|
+
* position; `volume` changes plumb to the instance gain, and `effectOverrides` to the instance's effect
|
|
29
|
+
* parameters — both put onto every instance the emitter gets. Each frame it forwards the listener pose,
|
|
29
30
|
* refreshes the spatial live set, and ticks sopra.
|
|
30
31
|
*
|
|
31
32
|
* **Two play paths**, chosen once at {@link link} (routing is fixed for the lifetime of the link —
|
|
@@ -66,7 +67,7 @@ export class AudioEmitterSystem extends System {
|
|
|
66
67
|
acousticLive = [];
|
|
67
68
|
|
|
68
69
|
/**
|
|
69
|
-
* Per-entity records: { emitter, transform, managed, instance, onVolume }. For a managed (3D)
|
|
70
|
+
* Per-entity records: { emitter, transform, managed, instance, onVolume, effectOverrides, onEffectOverride, ... }. For a managed (3D)
|
|
70
71
|
* emitter the playing instance lives in {@link liveSet} (record.instance stays null); for a
|
|
71
72
|
* direct (2D) emitter it is held here.
|
|
72
73
|
* @type {object[]}
|
|
@@ -144,11 +145,25 @@ export class AudioEmitterSystem extends System {
|
|
|
144
145
|
// class doc.
|
|
145
146
|
const managed = emitter.autoplay && emitter.event.is3D && emitter.event.rootClip.loops();
|
|
146
147
|
|
|
147
|
-
const record = {
|
|
148
|
+
const record = {
|
|
149
|
+
emitter, transform, managed, instance: null, onVolume: null, onEnded: null, onMoved: null,
|
|
150
|
+
// held here, so unlink detaches what link attached even if the field was replaced since
|
|
151
|
+
effectOverrides: emitter.effectOverrides,
|
|
152
|
+
onEffectOverride: null
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// Effect overrides move whichever instance is current, on either route. Checked first: an override
|
|
156
|
+
// written before the link that the event has no parameter for throws HERE, before anything is
|
|
157
|
+
// registered or played. They are attached - and every later write checked as it is written - once
|
|
158
|
+
// the record is stored, below, when nothing left in the link can fail and leave them attached to a
|
|
159
|
+
// record that never was.
|
|
160
|
+
record.effectOverrides.checkAttach(emitter.event);
|
|
161
|
+
record.onEffectOverride = (effectIndex, name, value, timeConstant) => this.#moveEffectParam(record, entity, effectIndex, name, value, timeConstant);
|
|
148
162
|
|
|
149
163
|
if (managed) {
|
|
150
164
|
const pathing = emitter.acoustic && this.acousticSim !== null && this.acousticSim.pathing;
|
|
151
|
-
|
|
165
|
+
// the live set puts the overrides onto every instance it promotes
|
|
166
|
+
this.liveSet.add(entity, emitter.event, transform.translation, volume2dB(emitter.volume.getValue()), emitter.acoustic, pathing, emitter.sourceRadius, transform.rotation, emitter.directivity, record.effectOverrides);
|
|
152
167
|
record.onVolume = () => this.liveSet.setGainDb(entity, volume2dB(emitter.volume.getValue()));
|
|
153
168
|
|
|
154
169
|
// The live set reads the translation through a live view, but a Transform64 cannot say it
|
|
@@ -166,12 +181,27 @@ export class AudioEmitterSystem extends System {
|
|
|
166
181
|
}
|
|
167
182
|
}
|
|
168
183
|
record.onVolume = () => this.#applyVolume(record);
|
|
184
|
+
|
|
185
|
+
if (record.instance !== null && emitter.event.is3D) {
|
|
186
|
+
// The instance holds the translation's live view, and reads it only when told it moved -
|
|
187
|
+
// the announcement is how it is told, as it is for the live set below
|
|
188
|
+
record.onMoved = () => record.instance?.moved();
|
|
189
|
+
|
|
190
|
+
this.entityManager.dataset.addEntityEventListener(entity, TRANSFORM64_EVENT_CHANGE, record.onMoved);
|
|
191
|
+
}
|
|
169
192
|
}
|
|
170
193
|
|
|
171
194
|
emitter.volume.onChanged.add(record.onVolume);
|
|
172
195
|
|
|
173
196
|
this.data[entity] = record;
|
|
174
197
|
|
|
198
|
+
record.effectOverrides.attach(emitter.event, record.onEffectOverride);
|
|
199
|
+
|
|
200
|
+
// a direct instance was built above, at the event's definition
|
|
201
|
+
if (record.instance !== null && record.instance.state !== EventInstanceState.Stopped) {
|
|
202
|
+
record.effectOverrides.applyTo(record.instance);
|
|
203
|
+
}
|
|
204
|
+
|
|
175
205
|
// A one-shot whose buffers are already decoded resolves its timeline inside playEvent and can
|
|
176
206
|
// finish there and then — before the subscription in #play exists, and while the record is still
|
|
177
207
|
// unreachable. Report that end here instead, once the link is complete, so an `on.ended` handler
|
|
@@ -197,10 +227,13 @@ export class AudioEmitterSystem extends System {
|
|
|
197
227
|
delete this.data[entity];
|
|
198
228
|
|
|
199
229
|
emitter.volume.onChanged.remove(record.onVolume);
|
|
230
|
+
record.effectOverrides.detach(record.onEffectOverride);
|
|
200
231
|
|
|
201
|
-
if (record.
|
|
232
|
+
if (record.onMoved !== null) {
|
|
202
233
|
this.entityManager.dataset.removeEntityEventListener(entity, TRANSFORM64_EVENT_CHANGE, record.onMoved);
|
|
234
|
+
}
|
|
203
235
|
|
|
236
|
+
if (record.managed) {
|
|
204
237
|
this.liveSet.remove(entity); // demotes (hard cut) if live, then unregisters
|
|
205
238
|
} else if (record.instance !== null) {
|
|
206
239
|
this.directInstances.delete(record.instance);
|
|
@@ -255,7 +288,7 @@ export class AudioEmitterSystem extends System {
|
|
|
255
288
|
|
|
256
289
|
const instance = this.sopra.playEvent(event, {
|
|
257
290
|
busId: event.busId,
|
|
258
|
-
// a live view over the transform's buffer,
|
|
291
|
+
// a live view over the transform's buffer, read again each time the entity announces a move
|
|
259
292
|
position: transform.translation,
|
|
260
293
|
oneShot,
|
|
261
294
|
acoustic: emitter.acoustic,
|
|
@@ -290,6 +323,137 @@ export class AudioEmitterSystem extends System {
|
|
|
290
323
|
}
|
|
291
324
|
}
|
|
292
325
|
|
|
326
|
+
/**
|
|
327
|
+
* Carry one change of an emitter's {@link AudioEmitter.effectOverrides} to its current instance. With
|
|
328
|
+
* none — dormant, or a one-shot that has ended — there is nothing to move: the next instance is built
|
|
329
|
+
* at the overrides as they then stand. A contention fade is not current; like the gain, it finishes
|
|
330
|
+
* as it was.
|
|
331
|
+
* @param {object} record the emitter's link record
|
|
332
|
+
* @param {number} entity
|
|
333
|
+
* @param {number} effectIndex
|
|
334
|
+
* @param {string} name
|
|
335
|
+
* @param {number} value
|
|
336
|
+
* @param {number} timeConstant 0 moves it now; above 0 glides
|
|
337
|
+
*/
|
|
338
|
+
#moveEffectParam(record, entity, effectIndex, name, value, timeConstant) {
|
|
339
|
+
// entity ids are reused: a record that is no longer the entity's must not move whoever has it now
|
|
340
|
+
if (this.data[entity] !== record) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const instance = this.instanceFor(entity);
|
|
345
|
+
|
|
346
|
+
if (instance === null || instance.state === EventInstanceState.Stopped) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (timeConstant > 0) {
|
|
351
|
+
instance.approachEffectParam(effectIndex, name, value, timeConstant);
|
|
352
|
+
} else {
|
|
353
|
+
instance.setEffectParam(effectIndex, name, value);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* The listener this system follows: its dataset, entity and transform, and the transform's
|
|
359
|
+
* translation view handed to sopra, taken once rather than read off the transform each frame (that
|
|
360
|
+
* getter builds a new view on every read). Null until a listener is seen.
|
|
361
|
+
* @type {EntityComponentDataset|null}
|
|
362
|
+
*/
|
|
363
|
+
#listener_ecd = null;
|
|
364
|
+
|
|
365
|
+
/** @type {number} */
|
|
366
|
+
#listener_entity = -1;
|
|
367
|
+
|
|
368
|
+
/** @type {Transform64|null} */
|
|
369
|
+
#listener_transform = null;
|
|
370
|
+
|
|
371
|
+
/** @type {Float64Array|null} */
|
|
372
|
+
#listener_position = null;
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Tells sopra the listener moved, when its transform announces a write: every 3D instance re-attenuates
|
|
376
|
+
* on the next tick, and none does between moves.
|
|
377
|
+
*/
|
|
378
|
+
#on_listener_moved = () => {
|
|
379
|
+
this.sopra.setListener(this.#listener_position);
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* The followed listener's entity was removed, and its listeners with it. Forget it, so the next
|
|
384
|
+
* update follows whatever listener there is then — the same entity rebuilt from the same components
|
|
385
|
+
* included, which comes back with the same id and transform and would otherwise look followed already.
|
|
386
|
+
* sopra keeps the last listener position until then, as it does with no listener at all.
|
|
387
|
+
*/
|
|
388
|
+
#on_listener_removed = () => {
|
|
389
|
+
this.#listener_ecd = null;
|
|
390
|
+
this.#listener_entity = -1;
|
|
391
|
+
this.#listener_transform = null;
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Follow `entity` as the listener, if it is not the one followed already: subscribe to its transform's
|
|
396
|
+
* announcements and hand sopra its position, which is itself a move.
|
|
397
|
+
*
|
|
398
|
+
* @param {EntityComponentDataset} ecd
|
|
399
|
+
* @param {number} entity
|
|
400
|
+
* @param {Transform64} transform
|
|
401
|
+
*/
|
|
402
|
+
#follow_listener(ecd, entity, transform) {
|
|
403
|
+
// the transform too: an entity id is reused, and a dataset can be swapped
|
|
404
|
+
if (ecd === this.#listener_ecd && entity === this.#listener_entity && transform === this.#listener_transform) {
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
this.#unfollow_listener();
|
|
409
|
+
|
|
410
|
+
this.#listener_ecd = ecd;
|
|
411
|
+
this.#listener_entity = entity;
|
|
412
|
+
this.#listener_transform = transform;
|
|
413
|
+
this.#listener_position = transform.translation;
|
|
414
|
+
|
|
415
|
+
ecd.addEntityEventListener(entity, TRANSFORM64_EVENT_CHANGE, this.#on_listener_moved);
|
|
416
|
+
ecd.addEntityEventListener(entity, EventType.EntityRemoved, this.#on_listener_removed);
|
|
417
|
+
|
|
418
|
+
this.sopra.setListener(this.#listener_position);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* @param {EntityComponentDataset} dataset
|
|
423
|
+
*/
|
|
424
|
+
handleDatasetDetached(dataset) {
|
|
425
|
+
// the listener followed lives in that dataset: leave nothing subscribed there
|
|
426
|
+
if (dataset === this.#listener_ecd) {
|
|
427
|
+
this.#unfollow_listener();
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* @param {EntityManager} entityManager
|
|
433
|
+
* @returns {Promise<void>}
|
|
434
|
+
*/
|
|
435
|
+
async shutdown(entityManager) {
|
|
436
|
+
// a removed system keeps no listener subscription, nor through it itself alive
|
|
437
|
+
this.#unfollow_listener();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Stop following the listener followed now, if any.
|
|
442
|
+
*/
|
|
443
|
+
#unfollow_listener() {
|
|
444
|
+
const ecd = this.#listener_ecd;
|
|
445
|
+
|
|
446
|
+
if (ecd === null) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// false, harmlessly, when that entity is gone: its listeners went with it
|
|
451
|
+
ecd.removeEntityEventListener(this.#listener_entity, TRANSFORM64_EVENT_CHANGE, this.#on_listener_moved);
|
|
452
|
+
ecd.removeEntityEventListener(this.#listener_entity, EventType.EntityRemoved, this.#on_listener_removed);
|
|
453
|
+
|
|
454
|
+
this.#on_listener_removed();
|
|
455
|
+
}
|
|
456
|
+
|
|
293
457
|
update(timeDelta) {
|
|
294
458
|
const sopra = this.sopra;
|
|
295
459
|
|
|
@@ -309,18 +473,18 @@ export class AudioEmitterSystem extends System {
|
|
|
309
473
|
const listenerTransform = ecd.getComponent(soundListener.entity, Transform64);
|
|
310
474
|
|
|
311
475
|
if (listenerTransform !== undefined) {
|
|
476
|
+
this.#follow_listener(ecd, soundListener.entity, listenerTransform);
|
|
477
|
+
|
|
312
478
|
/*
|
|
313
479
|
The position stays the transform's own view: it is a live one, so a listener that
|
|
314
480
|
walks needs no second write, and every consumer of it below indexes the three
|
|
315
481
|
numbers rather than reading `.x`. The reverb is the exception, and reads them
|
|
316
482
|
off the transform by component where it is called.
|
|
317
483
|
*/
|
|
318
|
-
listenerPosition =
|
|
484
|
+
listenerPosition = this.#listener_position;
|
|
319
485
|
|
|
320
486
|
// the rotation, by contrast, is handed to a renderer that steers by `q.x`
|
|
321
487
|
listenerRotation = t64_read_rotation(LISTENER_ROTATION, listenerTransform);
|
|
322
|
-
|
|
323
|
-
sopra.setListener(listenerPosition);
|
|
324
488
|
}
|
|
325
489
|
}
|
|
326
490
|
}
|
|
@@ -65,14 +65,19 @@ export class LiveEmitterSet {
|
|
|
65
65
|
* @param {number} [sourceRadius] apparent acoustic radius for volumetric occlusion (default 0.5)
|
|
66
66
|
* @param {Quaternion|null} [orientation] shared source orientation ref (tracks the entity), for directivity
|
|
67
67
|
* @param {AcousticDirectivity|null} [directivity] source radiation directivity (null = omni)
|
|
68
|
+
* @param {EffectParamOverrides|null} [effectOverrides] the emitter's own effect parameters, held by
|
|
69
|
+
* reference and put onto every promoted instance (null = none). Moving the live instance as they
|
|
70
|
+
* change is the owner's business: they reach it through {@link instanceOf}.
|
|
68
71
|
*/
|
|
69
|
-
add(entity: number, event: EventDescription, position: Float64Array, gainDb?: number, acoustic?: boolean, pathing?: boolean, sourceRadius?: number, orientation?: Quaternion | null, directivity?: AcousticDirectivity | null): void;
|
|
72
|
+
add(entity: number, event: EventDescription, position: Float64Array, gainDb?: number, acoustic?: boolean, pathing?: boolean, sourceRadius?: number, orientation?: Quaternion | null, directivity?: AcousticDirectivity | null, effectOverrides?: EffectParamOverrides | null): void;
|
|
70
73
|
/**
|
|
71
|
-
* Report that a registered emitter moved, so the broadphase refits it
|
|
74
|
+
* Report that a registered emitter moved, so the broadphase refits it and its instance, if it is
|
|
75
|
+
* sounding, puts itself where it now is. No-op for an unknown entity.
|
|
72
76
|
*
|
|
73
77
|
* The position is a live view, so whatever reads it reads the current value - what the set cannot
|
|
74
78
|
* do is notice that it was written. {@link refresh} considers only what this reported, which is
|
|
75
|
-
* what keeps a dormant emitter free: nothing visits it until it moves.
|
|
79
|
+
* what keeps a dormant emitter free: nothing visits it until it moves. The instance is the same: it
|
|
80
|
+
* reads the view only when told ({@link EventInstance#moved}), a fading one included.
|
|
76
81
|
* @param {number} entity
|
|
77
82
|
*/
|
|
78
83
|
moved(entity: number): void;
|
|
@@ -107,4 +112,5 @@ export class LiveEmitterSet {
|
|
|
107
112
|
refresh(listenerPosition: number[] | Float64Array): void;
|
|
108
113
|
#private;
|
|
109
114
|
}
|
|
115
|
+
export type EffectParamOverrides = import("../../sopra/runtime/EffectParamOverrides.js").EffectParamOverrides;
|
|
110
116
|
//# sourceMappingURL=LiveEmitterSet.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveEmitterSet.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/LiveEmitterSet.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LiveEmitterSet.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/audio/LiveEmitterSet.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH;IA4EI;;;OAGG;IACH,6EAFW;QAAC,MAAM,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAC;QAAC,cAAc,CAAC,EAAC,MAAM,CAAA;KAAC,EAO1E;IAED;;OAEG;IACH,wBAEC;IAED;;OAEG;IACH,mBAEC;IAED;;;OAGG;IACH,eAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,mBAHW,MAAM,GACJ,gBAAc,SAAS,CAInC;IAED;;;;;;;;;;;;;;OAcG;IACH,YAbW,MAAM,qCAEN,YAAY,WACZ,MAAM,aACN,OAAO,YACP,OAAO,iBACP,MAAM,gBACN,aAAW,IAAI,gBACf,sBAAoB,IAAI,oBACxB,oBAAoB,GAAC,IAAI,QASnC;IAED;;;;;;;;;OASG;IACH,cAFW,MAAM,QAOhB;IAED;;;;OAIG;IACH,+CAFmC,IAAI,QAMtC;IAED;;;;;;;OAOG;IACH,kBAHW,MAAM,UACN,MAAM,QAehB;IAED;;;OAGG;IACH,eAFW,MAAM,QAwBhB;IAED;;;;;;;OAOG;IACH,0BAFW,MAAM,EAAE,GAAC,YAAY,QA+D/B;;CAuFJ;mCA/ZY,OAAO,6CAA6C,EAAE,oBAAoB"}
|
|
@@ -2,6 +2,10 @@ import { EventInstanceState } from "../../sopra/runtime/EventInstance.js";
|
|
|
2
2
|
import { SpatialAudioIndex } from "./SpatialAudioIndex.js";
|
|
3
3
|
import { v3_distance } from "../../../../core/geom/vec3/v3_distance.js";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {import("../../sopra/runtime/EffectParamOverrides.js").EffectParamOverrides} EffectParamOverrides
|
|
7
|
+
*/
|
|
8
|
+
|
|
5
9
|
/**
|
|
6
10
|
* Sort rank entries nearest-first by effective (stickiness-discounted) distance.
|
|
7
11
|
* @param {{effective:number}} a
|
|
@@ -72,10 +76,11 @@ export class LiveEmitterSet {
|
|
|
72
76
|
#fadeOutSeconds;
|
|
73
77
|
|
|
74
78
|
/**
|
|
75
|
-
* entity -> { event, position, gainDb, playingSince }. `gainDb` is the per-emitter
|
|
76
|
-
* (e.g. the owning `AudioEmitter.volume` in dB)
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
+
* entity -> { event, position, gainDb, playingSince, effectOverrides, ... }. `gainDb` is the per-emitter
|
|
80
|
+
* instance gain (e.g. the owning `AudioEmitter.volume` in dB) and `effectOverrides` the emitter's own
|
|
81
|
+
* effect parameters, both re-applied on every promotion so they survive a demote→re-promote cycle;
|
|
82
|
+
* `playingSince` carries the continuous-clock phase (see {@link add}).
|
|
83
|
+
* @type {Map<number, {event: EventDescription, position: Float64Array, gainDb: number, playingSince: number, acoustic: boolean, pathing: boolean, sourceRadius: number, orientation: Quaternion|null, directivity: AcousticDirectivity|null, effectOverrides: EffectParamOverrides|null}>}
|
|
79
84
|
*/
|
|
80
85
|
#emitters = new Map();
|
|
81
86
|
|
|
@@ -167,24 +172,32 @@ export class LiveEmitterSet {
|
|
|
167
172
|
* @param {number} [sourceRadius] apparent acoustic radius for volumetric occlusion (default 0.5)
|
|
168
173
|
* @param {Quaternion|null} [orientation] shared source orientation ref (tracks the entity), for directivity
|
|
169
174
|
* @param {AcousticDirectivity|null} [directivity] source radiation directivity (null = omni)
|
|
175
|
+
* @param {EffectParamOverrides|null} [effectOverrides] the emitter's own effect parameters, held by
|
|
176
|
+
* reference and put onto every promoted instance (null = none). Moving the live instance as they
|
|
177
|
+
* change is the owner's business: they reach it through {@link instanceOf}.
|
|
170
178
|
*/
|
|
171
|
-
add(entity, event, position, gainDb = 0, acoustic = false, pathing = false, sourceRadius = 0.5, orientation = null, directivity = null) {
|
|
179
|
+
add(entity, event, position, gainDb = 0, acoustic = false, pathing = false, sourceRadius = 0.5, orientation = null, directivity = null, effectOverrides = null) {
|
|
172
180
|
this.#index.add(entity, event, position);
|
|
173
181
|
// playingSince: continuous-clock semantics — the emitter has been "playing" since it linked, so a
|
|
174
182
|
// later promotion resumes the loop at the phase it should be at (see #promote + EventInstance startTime).
|
|
175
|
-
this.#emitters.set(entity, { event, position, gainDb, playingSince: this.#sopra.currentTime, acoustic, pathing, sourceRadius, orientation, directivity });
|
|
183
|
+
this.#emitters.set(entity, { event, position, gainDb, playingSince: this.#sopra.currentTime, acoustic, pathing, sourceRadius, orientation, directivity, effectOverrides });
|
|
176
184
|
}
|
|
177
185
|
|
|
178
186
|
/**
|
|
179
|
-
* Report that a registered emitter moved, so the broadphase refits it
|
|
187
|
+
* Report that a registered emitter moved, so the broadphase refits it and its instance, if it is
|
|
188
|
+
* sounding, puts itself where it now is. No-op for an unknown entity.
|
|
180
189
|
*
|
|
181
190
|
* The position is a live view, so whatever reads it reads the current value - what the set cannot
|
|
182
191
|
* do is notice that it was written. {@link refresh} considers only what this reported, which is
|
|
183
|
-
* what keeps a dormant emitter free: nothing visits it until it moves.
|
|
192
|
+
* what keeps a dormant emitter free: nothing visits it until it moves. The instance is the same: it
|
|
193
|
+
* reads the view only when told ({@link EventInstance#moved}), a fading one included.
|
|
184
194
|
* @param {number} entity
|
|
185
195
|
*/
|
|
186
196
|
moved(entity) {
|
|
187
197
|
this.#index.refresh(entity);
|
|
198
|
+
|
|
199
|
+
this.#live.get(entity)?.moved();
|
|
200
|
+
this.#fading.get(entity)?.moved();
|
|
188
201
|
}
|
|
189
202
|
|
|
190
203
|
/**
|
|
@@ -370,6 +383,13 @@ export class LiveEmitterSet {
|
|
|
370
383
|
this.#fading.delete(entity);
|
|
371
384
|
}
|
|
372
385
|
});
|
|
386
|
+
|
|
387
|
+
// and the emitter's effect parameters, the way the gain is replayed: the fresh instance was built at
|
|
388
|
+
// the event's definition. Last, once the instance is tracked: an override the event cannot take
|
|
389
|
+
// throws, and must not leave a sounding instance nobody will ever stop.
|
|
390
|
+
if (record.effectOverrides !== null) {
|
|
391
|
+
record.effectOverrides.applyTo(instance);
|
|
392
|
+
}
|
|
373
393
|
}
|
|
374
394
|
|
|
375
395
|
/**
|
|
@@ -67,6 +67,10 @@ export class AudioEventTriggerRule {
|
|
|
67
67
|
priority: number;
|
|
68
68
|
stealMode: number;
|
|
69
69
|
virtualThresholdDb: number;
|
|
70
|
+
effects: {
|
|
71
|
+
type: string;
|
|
72
|
+
data: any;
|
|
73
|
+
}[];
|
|
70
74
|
};
|
|
71
75
|
};
|
|
72
76
|
fromJSON(json: any): void;
|
|
@@ -131,6 +135,10 @@ export class AudioEventTrigger {
|
|
|
131
135
|
priority: number;
|
|
132
136
|
stealMode: number;
|
|
133
137
|
virtualThresholdDb: number;
|
|
138
|
+
effects: {
|
|
139
|
+
type: string;
|
|
140
|
+
data: any;
|
|
141
|
+
}[];
|
|
134
142
|
};
|
|
135
143
|
}[];
|
|
136
144
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioEventTrigger.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTrigger.js"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH;IAuBI;;;;;OAKG;IACH,wBALW,MAAM,SACN,gBAAgB,cAChB,MAAM,GAAC,IAAI,GACT,qBAAqB,CAUjC;IAuCD;;;OAGG;IACH,4BAFa,qBAAqB,CAMjC;IAlFD;;;;OAIG;IACH,YAFU,MAAM,CAEA;IAEhB;;;;OAIG;IACH,WAFU,MAAM,GAAC,IAAI,CAEJ;IAEjB;;;;OAIG;IACH,OAFU,gBAAgB,CAEK;IAkB/B;;;OAGG;IACH,cAHW,qBAAqB,GACnB,OAAO,CAMnB;IAED,eAMC;IAED
|
|
1
|
+
{"version":3,"file":"AudioEventTrigger.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTrigger.js"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH;IAuBI;;;;;OAKG;IACH,wBALW,MAAM,SACN,gBAAgB,cAChB,MAAM,GAAC,IAAI,GACT,qBAAqB,CAUjC;IAuCD;;;OAGG;IACH,4BAFa,qBAAqB,CAMjC;IAlFD;;;;OAIG;IACH,YAFU,MAAM,CAEA;IAEhB;;;;OAIG;IACH,WAFU,MAAM,GAAC,IAAI,CAEJ;IAEjB;;;;OAIG;IACH,OAFU,gBAAgB,CAEK;IAkB/B;;;OAGG;IACH,cAHW,qBAAqB,GACnB,OAAO,CAMnB;IAED,eAMC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;MAMC;IAED,0BASC;CAWJ;AAED;;;;;;;;GAQG;AACH;IAcI;;;OAGG;IACH,mBAHW,qBAAqB,EAAE,GACrB,iBAAiB,CAQ7B;IA6CD;;;OAGG;IACH,4BAFa,iBAAiB,CAM7B;IA3ED;;;;;;;;;OASG;IACH,OAFU,qBAAqB,EAAE,CAEtB;IAcX;;;OAGG;IACH,cAHW,iBAAiB,GACf,OAAO,CAiBnB;IAED,eAUC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAIC;IAED,0BAEC;CAWJ;;;;iCA1LgC,4CAA4C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioEventTriggerSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH;;IACI,gCAA0B;
|
|
1
|
+
{"version":3,"file":"AudioEventTriggerSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH;;IACI,gCAA0B;IAY1B;;;OAGG;IACH,mFAEC;IAED;;;OAGG;IACH,uCAFW,iBAAiB,QAuB3B;IAED;;;OAGG;IACH,yCAFW,iBAAiB,QAmB3B;;CACJ;gDApF+C,gEAAgE;kCAEvD,wBAAwB"}
|
|
@@ -14,7 +14,11 @@ import { AudioEventTrigger, AudioEventTriggerRule } from "./AudioEventTrigger.js
|
|
|
14
14
|
*/
|
|
15
15
|
export class AudioEventTriggerSerializationAdapter extends BinaryClassSerializationAdapter {
|
|
16
16
|
klass = AudioEventTrigger;
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* 1: the embedded event record moved to its format 1 (insert effects) — `AudioEventTriggerSerializationUpgrader_0_1`.
|
|
19
|
+
* @type {number}
|
|
20
|
+
*/
|
|
21
|
+
version = 1;
|
|
18
22
|
|
|
19
23
|
/**
|
|
20
24
|
* @type {EventDescriptionSerializationAdapter}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry} BinarySerializationRegistry
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Version 0 → 1: each rule's embedded {@link EventDescription} record moved to its own format 1 (insert
|
|
6
|
+
* effects). The record carries no version tag of its own, so the component's version is what says which
|
|
7
|
+
* layout it is in; the rule's other fields are unchanged.
|
|
8
|
+
*/
|
|
9
|
+
export class AudioEventTriggerSerializationUpgrader_0_1 extends BinaryClassUpgrader {
|
|
10
|
+
/**
|
|
11
|
+
* @param {BinarySerializationRegistry} registry where the events' clip types are registered
|
|
12
|
+
*/
|
|
13
|
+
constructor(registry: BinarySerializationRegistry);
|
|
14
|
+
#private;
|
|
15
|
+
}
|
|
16
|
+
export type BinarySerializationRegistry = import("../../../ecs/storage/binary/BinarySerializationRegistry.js").BinarySerializationRegistry;
|
|
17
|
+
import { BinaryClassUpgrader } from "../../../ecs/storage/binary/BinaryClassUpgrader.js";
|
|
18
|
+
//# sourceMappingURL=AudioEventTriggerSerializationUpgrader_0_1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioEventTriggerSerializationUpgrader_0_1.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.js"],"names":[],"mappings":"AAMA;;GAEG;AAEH;;;;GAIG;AACH;IASI;;OAEG;IACH,sBAFW,2BAA2B,EAMrC;;CAmBJ;0CA3CY,OAAO,4DAA4D,EAAE,2BAA2B;oCANzE,oDAAoD"}
|