본문으로 건너뛰기

Facade API

Facade는 일반 웹 애플리케이션의 권장 진입점입니다. SoundTrace가 장면 수명주기를 관리하고 Listener, Source, Mesh가 앱의 3D 상태를 표현합니다.

Web SDK 개요 · Native API

기본 흐름

const sound = await SoundTrace.create(audioContext, options);

sound.listener.setPose(listenerPose);
const mesh = sound.addMesh(meshOptions);
const source = sound.addSource(sourceOptions);

const spatial = await source.play(inputNode);
spatial.connect(sound.output).connect(audioContext.destination);

await sound.update(0);

ST와 worker-hosted MT에서 이 호출 흐름은 같습니다. MT의 동기 native getter 대신 debugSnapshot() 같은 비동기 readback을 사용합니다.

SoundTrace 옵션

옵션기본값설명
mode미지정'single_thread', 'multi_thread', 'gpu' 중 하나
thread'auto'고급 WASM 선택: 'auto', 'st', 'mt'; mode가 우선
quality'balanced''fast', 'balanced', 'quality'
throughput미지정MT worker 예산: 'low', 'medium', 'max'
coordinateBasis코어 좌표계렌더러 좌표계를 SDK 좌표계로 변환
coreBaseUrl패키지 내부st/, mt/가 들어 있는 코어 URL
assetBaseUrl패키지 내부재질과 HRTF asset URL
propagationThreadCount엔진 기본값MT propagation thread 수의 저수준 override
defaultMeshBuild엔진 기본값addMesh()가 사용할 기본 BVH build 옵션
sceneRatio1.0장면 길이 단위당 미터. 지오메트리 사전 스케일과 혼용 금지(이중 스케일)
autoLoadMaterialstrue기본 재질을 로드해 이름 기반 매핑 활성화
transmissionModel'surface'직접음이 재질을 투과할 때의 에너지 감쇠 모델. 재질 투과 모델 참고
debugfalse초기화 진단 로그 출력

Three.js는 카메라가 -Z를 바라보므로 다음 basis로 시작할 수 있습니다.

const sound = await SoundTrace.create(audioContext, {
mode: 'single_thread',
coordinateBasis: {
right: [-1, 0, 0],
up: [0, 1, 0],
forward: [0, 0, -1],
},
});

주요 API

SoundTrace

API설명
SoundTrace.create(ctx, options?)엔진을 생성하고 로드 (생성자 + load())
output / audioContextmaster output node와 앱이 넘긴 AudioContext
listener장면의 단일 청취자
addMesh(options)음향 geometry 추가
removeMesh(mesh)geometry 제거
addSource(options)공간 음원 추가
setQuality(tier)품질 preset 변경
setAudioOption(options)block과 출력 channel override
loadHrtf(mode, source?)packaged 또는 custom HRTF 로드
loadMaterialAssets()재질 테이블을 수동 로드 (autoLoadMaterials: false일 때)
enableGpu()WebGPU 전파를 켜고 성공 여부를 반환. 미지원이면 false + CPU 유지
update(dt?)장면을 갱신하고 propagation 실행
debugSnapshot(options?)MT 호환 비동기 진단 snapshot
getStatistics(options?)valid path·ray·메모리 통계 (async)
getGpuStats()GPU dispatch/fallback 카운터 (async)
getIRs()최근 propagation의 path별 impulse response (async)
renderMonoImpulseResponse(source, sec)오프라인 mono IR 렌더. 출력 채널이 1일 때만 사용
reset()엔진 상태 초기화 (async)
dispose()SDK가 소유한 리소스 해제. 멱등, using과 호환

Listener

sound.listener
.setPose({ position: [0, 1.6, 0], orientation: [0, 0, 0, 1] })
.setRenderOptions({ hrtfQuality: 'medium' });

장면에는 listener가 하나 있습니다. listener는 SoundTrace가 소유하므로 별도로 dispose하지 않습니다.

출력 렌더러는 setOutputMode()로 바꿉니다. 기본값 'hrtf'는 바이노럴 렌더러이고, 'speaker'는 내부 Ambisonic 스피커 렌더러(1ch/2ch)를 선택합니다. HRTF 모드와 로드한 HRTF 테이블은 'hrtf' 출력에만 적용됩니다.

sound.listener.setOutputMode('speaker');

Source

const source = sound.addSource({
position: [2, 1, -1],
gain: 1,
paths: {
direct: true,
reflection: true,
diffraction: true,
reverberation: true,
},
});

source.setPose({ position: [1, 1, -2] });
source.setGain(0.8);
source.setPathEnabled('reverberation', false);

play(input, channels?)는 입력을 연결한 AudioWorkletNode를 반환합니다. 출력은 앱이 sound.output 또는 다른 Web Audio graph에 연결합니다.

거리 감쇠

addSource()는 5종 path 전부에 기본 거리 감쇠 계수 { constant: 1, linear: 0, quadratic: 1 }을 적용합니다.

gain = 1 / (constant + linear * distance + quadratic * distance^2)

즉 기본 곡선은 1 / (1 + distance²)입니다. constant = 1이 거리 0 부근의 폭주를 막고, quadratic = 1이 역제곱에 가까운 감쇠를 만듭니다.

지향성

음원에 방향성을 주려면 각도별 대역 감쇠 테이블을 등록하고 활성화합니다.

source.setDirection([0, 0, -1]);
source.setDirectivityTable(anglesDeg, attenDbPerBand);
source.setDirectivityEnabled(true);

Mesh

const mesh = sound.addMesh({
vertices: geometry.attributes.position.array,
indices: geometry.index.array,
material: 'concrete',
});

mesh.setPose({
position: object.position.toArray(),
orientation: object.quaternion.toArray(),
scale: object.scale.toArray(),
});

indices는 메시 전체가 하나의 재질을 사용할 때 편리합니다. 면별 재질이 필요하면 { a, b, c, materialIndex } 형태의 triangles를 전달하세요.

생성 후에도 재질과 갱신 정책을 바꿀 수 있습니다.

API설명
setMaterial(material)메시 전체 재질 교체
setMaterialRange(triStart, triCount, material)triangle 범위별 재질 교체
setUpdateType(type) / getUpdateType()'static', 'refit', 'rebuild', 'dynamic'
setPose(pose)position, orientation, scale 갱신
dispose()메시와 collider 해제

움직이지 않는 벽은 'static', vertex만 바뀌는 geometry는 'refit', topology가 바뀌면 'rebuild'를 사용합니다.

재질 투과 모델

transmissionModel은 직접음이 벽 같은 재질을 통과할 때 에너지를 잃는 방식을 선택합니다.

동작
'surface' (기본)표면을 지날 때마다 재질의 투과 계수를 한 번 적용. 벽 두께와 무관
'solid'두께 인식: ray가 solid 내부를 지나는 거리에 재질별 per-band 두께를 적용. 두꺼운 벽이 더 많이 차단
const sound = await SoundTrace.create(audioContext, {
mode: 'single_thread',
transmissionModel: 'solid',
});

'solid'는 두께가 저작된 재질만 전환하며, 두께가 없는 재질은 'surface' 동작을 유지합니다. 기본 재질 테이블에서는 22종 중 15종이 두께를 포함합니다.

경고

opt-in 옵션입니다 — 벽 너머 음원의 크기가 달라지므로, 기존 장면의 사운드를 유지해야 한다면 기본값을 그대로 두세요.

전파 path cache

모든 세션은 propagation path cache가 켜진 상태로 시작합니다(고정 seed, 크기 512). ST와 MT 양쪽에서 첫 프레임 이전에 적용되며 reset() 이후에도 다시 적용되므로, 캐시를 켜기 위해 별도로 호출할 API는 없습니다.

프레임 업데이트

pose 변경은 빠르게 기록할 수 있지만, propagation update는 동시에 하나만 실행하는 것이 안전합니다.

let updateInFlight: Promise<number> | undefined;

function frame(dt: number) {
if (!updateInFlight) {
updateInFlight = sound.update(dt).finally(() => {
updateInFlight = undefined;
});
}
}

수명주기

SoundTrace, Source, Meshdispose()를 지원합니다. SoundTrace.dispose()는 listener를 포함해 SDK가 소유한 리소스를 정리하며 여러 번 호출해도 안전합니다.

source.dispose();
mesh.dispose();
sound.dispose();

관련 문서