Skip to main content

Native API

The Native API is for advanced single-thread integrations that need direct control over scenes, listeners, sources, meshes, and BVHs. Ordinary applications should use the Facade API.

import { SoundTrace } from '@exarionai/soundtrace.js';
import {
BvhType,
PathType,
UpdateType,
type MeshBuildOptions,
} from '@exarionai/soundtrace.js/native';

Support scope

:::warning Current public type contract @exarionai/soundtrace.js/native exports the low-level classes and types, but the public return type of SoundTrace.create() is still the facade. A complete direct-native TypeScript entry flow through factories such as createScene(), createListener(), and createSource() is therefore not yet offered as a public contract.

Until the public types expand, use the facade. Casts into internal implementations and private deep imports carry no version-compatibility guarantee. :::

Direct-native control is also ST-only. On worker-hosted MT, the following surfaces throw SoundTraceMtUnsupportedError.

  • createScene(), createListener(), createSource()
  • createMesh(), createObject(), createCollider()
  • materials, propagator, diagnostics
  • createWorkletNode()
  • Synchronous native getters

MT applications should use the facade together with await sound.debugSnapshot().

Object model

ObjectRole
SoundSceneOwns objects, sources, and the single listener; runs propagation
SoundListenerManages listener pose, ray settings, and render options
SoundSourceManages source pose, gain, and per-path options
SoundMeshManages triangle geometry and its BLAS
SoundObjectManages scene transforms and mesh instances
SoundColliderBinds the lifecycles of a SoundMesh and a SoundObject
MaterialTableRegisters per-frequency-band materials
PropagatorQueries valid paths and profiles
DiagnosticsQueries ray, memory, and runtime diagnostics

Scene updates

A low-level scene is advanced in this order.

scene.tick(dt);
scene.updatePropagation();

scene.update(dt) is shorthand for running both in sequence.

A scene has exactly one listener.

scene.setListener(listener);
scene.addSource(source);
scene.addCollider(collider);

Geometry changes

ChangeAPIUpdate type
Transform onlyobject.setPosition(...) and friendsUpdated to match the object's state
Vertices onlymesh.updateVerticesAndRefit(...)UpdateType.Refit
Topology or BVH optionsmesh.setData(...)UpdateType.Rebuild

Use refit for animated geometry that keeps its topology — skinned animation and procedural deformation — together with a refit-capable LBVH family.

A vertex update is the core's exaMeshUpdateVerticesexaMeshRefit two-call protocol. mesh.updateVertices() only uploads the vertices and does not refit the BVH, so call mesh.updateVerticesAndRefit(), which does both, or follow up with mesh.refit() yourself. The vertex count must exactly match the count the mesh was built with.

mesh.updateVerticesAndRefit(vertices); // updateVertices + refit
object.setUpdateType(UpdateType.Refit);
scene.tick(dt);

SoundCollider folds both steps into one call.

collider.refitVertices(vertices); // updateVerticesAndRefit + setUpdateType(Refit)
scene.tick(dt);

When topology changes, ask for a rebuild explicitly.

mesh.setData(vertices, triangles, buildOptions);
object.setUpdateType(UpdateType.Rebuild);
scene.tick(dt);

collider.rebuild(vertices, triangles, buildOptions) performs the same combination.

BVH selection

TypeUse for
BvhType.HKDtreeStatic geometry such as walls and floors
BvhType.LBVHGeometry whose vertices change often
BvhType.LBVH_SIMD*LBVH with an explicit SIMD width
BvhType.LBVH_NWAY*N-way LBVH

BvhType.Default is a per-mesh sentinel meaning "follow the engine default". Use a concrete BVH type when setting a process-wide default.

const buildOptions: MeshBuildOptions = {
bvhType: BvhType.HKDtree,
bvhMaxDepth: 0,
primPerLeaf: 0,
};

Audio

Native realtime rendering also uses an AudioWorkletNode. The base contract is:

  • Sample rate: AudioContext.sampleRate
  • Block size: 128 samples
  • Output: 2-channel binaural

The facade's source.play() manages this setup and the graph connections. Use direct-native createWorkletNode() from application code only once its public factory types are provided.

Diagnostics

What you needFacadeNative ST
Valid paths and profilesawait debugSnapshot()Propagator
Ray and memory statisticsawait debugSnapshot()Diagnostics
Poses the app has setEntity stateNative object getters

On MT, never read propagation results through synchronous getters.