@aura3d/audio 2.0.3 → 3.0.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/dist/AudioSource.d.ts +2 -0
- package/dist/AudioSource.d.ts.map +1 -1
- package/dist/AudioSource.js +7 -0
- package/dist/AudioSource.js.map +1 -1
- package/dist/Footsteps.d.ts +47 -0
- package/dist/Footsteps.d.ts.map +1 -0
- package/dist/Footsteps.js +73 -0
- package/dist/Footsteps.js.map +1 -0
- package/dist/GameMixer.d.ts +69 -0
- package/dist/GameMixer.d.ts.map +1 -0
- package/dist/GameMixer.js +141 -0
- package/dist/GameMixer.js.map +1 -0
- package/dist/PositionalEmitter.d.ts +95 -0
- package/dist/PositionalEmitter.d.ts.map +1 -0
- package/dist/PositionalEmitter.js +199 -0
- package/dist/PositionalEmitter.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/AudioSource.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export declare class AudioSource {
|
|
|
12
12
|
private readonly options;
|
|
13
13
|
clip?: AudioClip;
|
|
14
14
|
loop: boolean;
|
|
15
|
+
/** Playback-rate multiplier; the positional emitter drives this for doppler. Defaults to 1. */
|
|
16
|
+
playbackRate: number;
|
|
15
17
|
readonly gain: GainNode;
|
|
16
18
|
private stateRef;
|
|
17
19
|
private node?;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioSource.d.ts","sourceRoot":"","sources":["../../../../packages/audio/src/AudioSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,WAAW;
|
|
1
|
+
{"version":3,"file":"AudioSource.d.ts","sourceRoot":"","sources":["../../../../packages/audio/src/AudioSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,WAAW;IAaV,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZpC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,+FAA+F;IAC/F,YAAY,SAAK;IACjB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAExB,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAwB;IACrC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,cAAc,CAAC,CAAS;gBAEH,OAAO,EAAE,kBAAkB;IAQxD,IAAI,KAAK,IAAI,gBAAgB,CAE5B;IAED,IAAI,CAAC,IAAI,SAAI,GAAG,IAAI;IA6BpB,IAAI,CAAC,IAAI,SAAI,GAAG,IAAI;IASpB,KAAK,IAAI,IAAI;IAQb,MAAM,IAAI,IAAI;IAKd,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,SAAI,GAAG,IAAI;IAS1E,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAQ7D,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAO9B,OAAO,IAAI,IAAI;IAKf,OAAO,CAAC,QAAQ;CAQjB"}
|
package/dist/AudioSource.js
CHANGED
|
@@ -2,6 +2,8 @@ export class AudioSource {
|
|
|
2
2
|
options;
|
|
3
3
|
clip;
|
|
4
4
|
loop;
|
|
5
|
+
/** Playback-rate multiplier; the positional emitter drives this for doppler. Defaults to 1. */
|
|
6
|
+
playbackRate = 1;
|
|
5
7
|
gain;
|
|
6
8
|
stateRef = "idle";
|
|
7
9
|
node;
|
|
@@ -27,6 +29,11 @@ export class AudioSource {
|
|
|
27
29
|
const source = this.options.context.createBufferSource();
|
|
28
30
|
source.buffer = this.clip.buffer;
|
|
29
31
|
source.loop = this.loop;
|
|
32
|
+
// Guarded: minimal mock contexts in unit tests may not implement playbackRate.
|
|
33
|
+
const rate = source.playbackRate;
|
|
34
|
+
if (rate && Number.isFinite(this.playbackRate) && this.playbackRate > 0) {
|
|
35
|
+
rate.value = this.playbackRate;
|
|
36
|
+
}
|
|
30
37
|
source.connect(this.gain);
|
|
31
38
|
const offset = Math.min(this.offsetSeconds, Math.max(0, this.clip.duration - Number.EPSILON));
|
|
32
39
|
if (this.spriteDuration === undefined)
|
package/dist/AudioSource.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioSource.js","sourceRoot":"","sources":["../../../../packages/audio/src/AudioSource.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,WAAW;
|
|
1
|
+
{"version":3,"file":"AudioSource.js","sourceRoot":"","sources":["../../../../packages/audio/src/AudioSource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Vec3Like } from "./AudioListener.js";
|
|
2
|
+
export type FootId = "left" | "right";
|
|
3
|
+
export interface FootPlantEvent {
|
|
4
|
+
readonly foot: FootId;
|
|
5
|
+
readonly surface: string;
|
|
6
|
+
readonly position?: Vec3Like;
|
|
7
|
+
readonly speed?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface FootstepEvidence {
|
|
10
|
+
readonly kind: "footstep-evidence";
|
|
11
|
+
readonly plantCount: number;
|
|
12
|
+
readonly lastCue: string | null;
|
|
13
|
+
readonly lastSurface: string | null;
|
|
14
|
+
readonly surfaceCount: number;
|
|
15
|
+
}
|
|
16
|
+
export interface FootstepPlayerOptions {
|
|
17
|
+
readonly surfaces?: Readonly<Record<string, readonly string[]>>;
|
|
18
|
+
readonly fallback?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Surface-tagged footstep hooks. Routes map foot-IK plant events (E2) to cue ids
|
|
22
|
+
* through `onPlant`; selection round-robins per surface so repeated steps on one
|
|
23
|
+
* material do not machine-gun the same sample. This class owns selection and
|
|
24
|
+
* telemetry only — actually sounding the cue stays with `GameAudio`, which knows
|
|
25
|
+
* buses, mute, and unlock.
|
|
26
|
+
*/
|
|
27
|
+
export declare class FootstepPlayer {
|
|
28
|
+
private readonly surfaces;
|
|
29
|
+
private readonly cursor;
|
|
30
|
+
private fallbackRef;
|
|
31
|
+
private plantCount;
|
|
32
|
+
private lastCue;
|
|
33
|
+
private lastSurface;
|
|
34
|
+
constructor(options?: FootstepPlayerOptions);
|
|
35
|
+
registerSurface(surface: string, cueIds: readonly string[]): void;
|
|
36
|
+
unregisterSurface(surface: string): boolean;
|
|
37
|
+
setFallback(cueId: string | undefined): void;
|
|
38
|
+
surfaceNames(): readonly string[];
|
|
39
|
+
/**
|
|
40
|
+
* Select the cue id for a plant event, or null when no surface or fallback cue
|
|
41
|
+
* is registered. Never throws on unknown surfaces — a missing footstep mapping
|
|
42
|
+
* is a content gap, not a runtime fault.
|
|
43
|
+
*/
|
|
44
|
+
onPlant(event: FootPlantEvent): string | null;
|
|
45
|
+
evidence(): FootstepEvidence;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=Footsteps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Footsteps.d.ts","sourceRoot":"","sources":["../../../../packages/audio/src/Footsteps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEtC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IACjE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,WAAW,CAAuB;gBAE9B,OAAO,GAAE,qBAA0B;IAO/C,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAMjE,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAK3C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAI5C,YAAY,IAAI,SAAS,MAAM,EAAE;IAIjC;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAoB7C,QAAQ,IAAI,gBAAgB;CAS7B"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface-tagged footstep hooks. Routes map foot-IK plant events (E2) to cue ids
|
|
3
|
+
* through `onPlant`; selection round-robins per surface so repeated steps on one
|
|
4
|
+
* material do not machine-gun the same sample. This class owns selection and
|
|
5
|
+
* telemetry only — actually sounding the cue stays with `GameAudio`, which knows
|
|
6
|
+
* buses, mute, and unlock.
|
|
7
|
+
*/
|
|
8
|
+
export class FootstepPlayer {
|
|
9
|
+
surfaces = new Map();
|
|
10
|
+
cursor = new Map();
|
|
11
|
+
fallbackRef;
|
|
12
|
+
plantCount = 0;
|
|
13
|
+
lastCue = null;
|
|
14
|
+
lastSurface = null;
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
for (const [surface, cues] of Object.entries(options.surfaces ?? {})) {
|
|
17
|
+
this.registerSurface(surface, cues);
|
|
18
|
+
}
|
|
19
|
+
this.fallbackRef = options.fallback;
|
|
20
|
+
}
|
|
21
|
+
registerSurface(surface, cueIds) {
|
|
22
|
+
if (cueIds.length === 0)
|
|
23
|
+
throw new Error(`Footstep surface "${surface}" needs at least one cue id.`);
|
|
24
|
+
this.surfaces.set(surface, [...cueIds]);
|
|
25
|
+
this.cursor.set(surface, 0);
|
|
26
|
+
}
|
|
27
|
+
unregisterSurface(surface) {
|
|
28
|
+
this.cursor.delete(surface);
|
|
29
|
+
return this.surfaces.delete(surface);
|
|
30
|
+
}
|
|
31
|
+
setFallback(cueId) {
|
|
32
|
+
this.fallbackRef = cueId;
|
|
33
|
+
}
|
|
34
|
+
surfaceNames() {
|
|
35
|
+
return [...this.surfaces.keys()];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Select the cue id for a plant event, or null when no surface or fallback cue
|
|
39
|
+
* is registered. Never throws on unknown surfaces — a missing footstep mapping
|
|
40
|
+
* is a content gap, not a runtime fault.
|
|
41
|
+
*/
|
|
42
|
+
onPlant(event) {
|
|
43
|
+
const cues = this.surfaces.get(event.surface);
|
|
44
|
+
let selected;
|
|
45
|
+
let surfaceKey = event.surface;
|
|
46
|
+
if (cues && cues.length > 0) {
|
|
47
|
+
const index = this.cursor.get(event.surface) ?? 0;
|
|
48
|
+
selected = cues[index % cues.length];
|
|
49
|
+
this.cursor.set(event.surface, index + 1);
|
|
50
|
+
}
|
|
51
|
+
else if (this.fallbackRef !== undefined) {
|
|
52
|
+
selected = this.fallbackRef;
|
|
53
|
+
surfaceKey = `${event.surface} (fallback)`;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
this.plantCount += 1;
|
|
59
|
+
this.lastCue = selected ?? null;
|
|
60
|
+
this.lastSurface = surfaceKey;
|
|
61
|
+
return selected ?? null;
|
|
62
|
+
}
|
|
63
|
+
evidence() {
|
|
64
|
+
return {
|
|
65
|
+
kind: "footstep-evidence",
|
|
66
|
+
plantCount: this.plantCount,
|
|
67
|
+
lastCue: this.lastCue,
|
|
68
|
+
lastSurface: this.lastSurface,
|
|
69
|
+
surfaceCount: this.surfaces.size
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=Footsteps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Footsteps.js","sourceRoot":"","sources":["../../../../packages/audio/src/Footsteps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { AudioBus } from "./AudioBus.js";
|
|
2
|
+
import type { AudioContextLike } from "./AudioContextManager.js";
|
|
3
|
+
import { AudioMixer } from "./AudioMixer.js";
|
|
4
|
+
export interface GameMixerBusLevel {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly volume: number;
|
|
7
|
+
readonly muted: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Effective output gain (0 when muted, else volume). This is the *target* gain,
|
|
10
|
+
* not a metered loudness reading — `metered` is false unless an analyser is
|
|
11
|
+
* attached, so evidence never claims audible output it did not measure.
|
|
12
|
+
*/
|
|
13
|
+
readonly level: number;
|
|
14
|
+
readonly metered: false;
|
|
15
|
+
}
|
|
16
|
+
export interface GameMixerEvidence {
|
|
17
|
+
readonly kind: "game-mixer-evidence";
|
|
18
|
+
readonly music: GameMixerBusLevel;
|
|
19
|
+
readonly sfx: GameMixerBusLevel;
|
|
20
|
+
readonly voice: GameMixerBusLevel;
|
|
21
|
+
readonly duckingActive: boolean;
|
|
22
|
+
readonly duckingRatio: number;
|
|
23
|
+
readonly muted: boolean;
|
|
24
|
+
readonly errors: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
export interface GameMixerOptions {
|
|
27
|
+
readonly musicVolume?: number;
|
|
28
|
+
readonly sfxVolume?: number;
|
|
29
|
+
readonly voiceVolume?: number;
|
|
30
|
+
readonly duckingRatio?: number;
|
|
31
|
+
readonly muted?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface GameMixer {
|
|
34
|
+
readonly mixer: AudioMixer;
|
|
35
|
+
readonly music: AudioBus;
|
|
36
|
+
readonly sfx: AudioBus;
|
|
37
|
+
readonly voice: AudioBus;
|
|
38
|
+
setMusicVolume(value: number): GameMixerEvidence;
|
|
39
|
+
setSfxVolume(value: number): GameMixerEvidence;
|
|
40
|
+
setVoiceVolume(value: number): GameMixerEvidence;
|
|
41
|
+
/** Duck the music bus while dialogue/voice is active; restores the base volume after. */
|
|
42
|
+
setDialogueActive(active: boolean): GameMixerEvidence;
|
|
43
|
+
setDuckingRatio(ratio: number): GameMixerEvidence;
|
|
44
|
+
setMuted(muted: boolean): GameMixerEvidence;
|
|
45
|
+
evidence(): GameMixerEvidence;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Game mixers on top of `AudioMixer`: music/sfx/voice buses with dialogue
|
|
49
|
+
* ducking and a single mute switch. Ducking scales the *effective* music gain
|
|
50
|
+
* while the authored base volume is retained for restore.
|
|
51
|
+
*/
|
|
52
|
+
export declare function createGameMixer(context: AudioContextLike, options?: GameMixerOptions): GameMixer;
|
|
53
|
+
export type FocusMutePolicy = "mute-on-blur" | "duck-on-blur" | "none";
|
|
54
|
+
export interface FocusPolicyHandlers {
|
|
55
|
+
readonly policy: FocusMutePolicy;
|
|
56
|
+
readonly onBlur: () => void;
|
|
57
|
+
readonly onFocus: () => void;
|
|
58
|
+
}
|
|
59
|
+
export interface FocusEventTargetLike {
|
|
60
|
+
addEventListener(type: string, listener: () => void): void;
|
|
61
|
+
removeEventListener(type: string, listener: () => void): void;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Mute/focus policy for a game mixer. Blur ducks or mutes the master bus;
|
|
65
|
+
* focus restores the pre-blur state. Returns a detach function.
|
|
66
|
+
*/
|
|
67
|
+
export declare function attachFocusPolicy(target: FocusEventTargetLike, mixer: GameMixer, policy?: FocusMutePolicy): () => void;
|
|
68
|
+
export declare function focusHandlersForMixer(mixer: GameMixer, policy: FocusMutePolicy): FocusPolicyHandlers;
|
|
69
|
+
//# sourceMappingURL=GameMixer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GameMixer.d.ts","sourceRoot":"","sources":["../../../../packages/audio/src/GameMixer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { AudioBus } from "./AudioBus.js";
|
|
2
|
+
import { AudioMixer } from "./AudioMixer.js";
|
|
3
|
+
function validateVolume(value, label) {
|
|
4
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
5
|
+
throw new Error(`${label} must be a non-negative finite number`);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
function busLevel(bus) {
|
|
9
|
+
return {
|
|
10
|
+
name: bus.name,
|
|
11
|
+
volume: bus.volume,
|
|
12
|
+
muted: bus.isMuted,
|
|
13
|
+
level: bus.isMuted ? 0 : bus.volume,
|
|
14
|
+
metered: false
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Game mixers on top of `AudioMixer`: music/sfx/voice buses with dialogue
|
|
19
|
+
* ducking and a single mute switch. Ducking scales the *effective* music gain
|
|
20
|
+
* while the authored base volume is retained for restore.
|
|
21
|
+
*/
|
|
22
|
+
export function createGameMixer(context, options = {}) {
|
|
23
|
+
const mixer = new AudioMixer(context);
|
|
24
|
+
const music = mixer.createBus("music");
|
|
25
|
+
const sfx = mixer.createBus("sfx");
|
|
26
|
+
const voice = mixer.createBus("voice");
|
|
27
|
+
let baseMusicVolume = options.musicVolume ?? 0.55;
|
|
28
|
+
let duckingRatio = options.duckingRatio ?? 0.35;
|
|
29
|
+
let duckingActive = false;
|
|
30
|
+
let muted = false;
|
|
31
|
+
const errors = [];
|
|
32
|
+
validateVolume(baseMusicVolume, "Game mixer musicVolume");
|
|
33
|
+
validateVolume(options.sfxVolume ?? 0.9, "Game mixer sfxVolume");
|
|
34
|
+
validateVolume(options.voiceVolume ?? 1, "Game mixer voiceVolume");
|
|
35
|
+
if (!Number.isFinite(duckingRatio) || duckingRatio < 0 || duckingRatio > 1) {
|
|
36
|
+
throw new Error("Game mixer duckingRatio must be between 0 and 1");
|
|
37
|
+
}
|
|
38
|
+
music.setVolume(baseMusicVolume);
|
|
39
|
+
sfx.setVolume(options.sfxVolume ?? 0.9);
|
|
40
|
+
voice.setVolume(options.voiceVolume ?? 1);
|
|
41
|
+
const applyMusicGain = () => {
|
|
42
|
+
music.setVolume(duckingActive ? baseMusicVolume * duckingRatio : baseMusicVolume);
|
|
43
|
+
};
|
|
44
|
+
const snapshot = () => ({
|
|
45
|
+
kind: "game-mixer-evidence",
|
|
46
|
+
music: busLevel(music),
|
|
47
|
+
sfx: busLevel(sfx),
|
|
48
|
+
voice: busLevel(voice),
|
|
49
|
+
duckingActive,
|
|
50
|
+
duckingRatio,
|
|
51
|
+
muted,
|
|
52
|
+
errors: [...errors]
|
|
53
|
+
});
|
|
54
|
+
const gameMixer = {
|
|
55
|
+
mixer,
|
|
56
|
+
music,
|
|
57
|
+
sfx,
|
|
58
|
+
voice,
|
|
59
|
+
setMusicVolume(value) {
|
|
60
|
+
validateVolume(value, "Game mixer musicVolume");
|
|
61
|
+
baseMusicVolume = value;
|
|
62
|
+
applyMusicGain();
|
|
63
|
+
return snapshot();
|
|
64
|
+
},
|
|
65
|
+
setSfxVolume(value) {
|
|
66
|
+
validateVolume(value, "Game mixer sfxVolume");
|
|
67
|
+
sfx.setVolume(value);
|
|
68
|
+
return snapshot();
|
|
69
|
+
},
|
|
70
|
+
setVoiceVolume(value) {
|
|
71
|
+
validateVolume(value, "Game mixer voiceVolume");
|
|
72
|
+
voice.setVolume(value);
|
|
73
|
+
return snapshot();
|
|
74
|
+
},
|
|
75
|
+
setDialogueActive(active) {
|
|
76
|
+
duckingActive = active;
|
|
77
|
+
applyMusicGain();
|
|
78
|
+
return snapshot();
|
|
79
|
+
},
|
|
80
|
+
setDuckingRatio(ratio) {
|
|
81
|
+
if (!Number.isFinite(ratio) || ratio < 0 || ratio > 1) {
|
|
82
|
+
throw new Error("Game mixer duckingRatio must be between 0 and 1");
|
|
83
|
+
}
|
|
84
|
+
duckingRatio = ratio;
|
|
85
|
+
applyMusicGain();
|
|
86
|
+
return snapshot();
|
|
87
|
+
},
|
|
88
|
+
setMuted(value) {
|
|
89
|
+
muted = value;
|
|
90
|
+
mixer.master.mute(value);
|
|
91
|
+
return snapshot();
|
|
92
|
+
},
|
|
93
|
+
evidence() {
|
|
94
|
+
return snapshot();
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
if (options.muted)
|
|
98
|
+
gameMixer.setMuted(true);
|
|
99
|
+
return gameMixer;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Mute/focus policy for a game mixer. Blur ducks or mutes the master bus;
|
|
103
|
+
* focus restores the pre-blur state. Returns a detach function.
|
|
104
|
+
*/
|
|
105
|
+
export function attachFocusPolicy(target, mixer, policy = "duck-on-blur") {
|
|
106
|
+
const handlers = focusHandlersForMixer(mixer, policy);
|
|
107
|
+
const onBlur = () => handlers.onBlur();
|
|
108
|
+
const onFocus = () => handlers.onFocus();
|
|
109
|
+
target.addEventListener("blur", onBlur);
|
|
110
|
+
target.addEventListener("focus", onFocus);
|
|
111
|
+
return () => {
|
|
112
|
+
target.removeEventListener("blur", onBlur);
|
|
113
|
+
target.removeEventListener("focus", onFocus);
|
|
114
|
+
handlers.onFocus();
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export function focusHandlersForMixer(mixer, policy) {
|
|
118
|
+
let blurred = false;
|
|
119
|
+
return {
|
|
120
|
+
policy,
|
|
121
|
+
onBlur: () => {
|
|
122
|
+
if (blurred || policy === "none")
|
|
123
|
+
return;
|
|
124
|
+
blurred = true;
|
|
125
|
+
if (policy === "mute-on-blur")
|
|
126
|
+
mixer.setMuted(true);
|
|
127
|
+
else
|
|
128
|
+
mixer.setDialogueActive(true);
|
|
129
|
+
},
|
|
130
|
+
onFocus: () => {
|
|
131
|
+
if (!blurred)
|
|
132
|
+
return;
|
|
133
|
+
blurred = false;
|
|
134
|
+
if (policy === "mute-on-blur")
|
|
135
|
+
mixer.setMuted(false);
|
|
136
|
+
else
|
|
137
|
+
mixer.setDialogueActive(false);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=GameMixer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GameMixer.js","sourceRoot":"","sources":["../../../../packages/audio/src/GameMixer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { AudioSource, type AudioSourceState } from "./AudioSource.js";
|
|
2
|
+
import type { AudioClip } from "./AudioClip.js";
|
|
3
|
+
import type { AudioContextLike } from "./AudioContextManager.js";
|
|
4
|
+
import type { Vec3Like } from "./AudioListener.js";
|
|
5
|
+
import { SpatialAudio } from "./SpatialAudio.js";
|
|
6
|
+
export type DistanceAttenuationModel = "inverse" | "linear" | "exponential";
|
|
7
|
+
export interface DistanceAttenuationOptions {
|
|
8
|
+
readonly refDistance?: number;
|
|
9
|
+
readonly maxDistance?: number;
|
|
10
|
+
readonly rolloffFactor?: number;
|
|
11
|
+
readonly model?: DistanceAttenuationModel;
|
|
12
|
+
}
|
|
13
|
+
export interface DopplerOptions {
|
|
14
|
+
readonly speedOfSound?: number;
|
|
15
|
+
readonly dopplerFactor?: number;
|
|
16
|
+
}
|
|
17
|
+
/** A hook that reports how occluded an emitter is from the listener (0 = clear, 1 = fully blocked). */
|
|
18
|
+
export type OcclusionHook = (emitter: Vec3Like, listener: Vec3Like) => number;
|
|
19
|
+
/**
|
|
20
|
+
* Pure distance-attenuation gain in [0, 1], mirroring the PannerNode models so
|
|
21
|
+
* evidence stays meaningful even when no WebAudio context exists (headless runs).
|
|
22
|
+
*/
|
|
23
|
+
export declare function computeDistanceAttenuation(distance: number, options?: DistanceAttenuationOptions): number;
|
|
24
|
+
/**
|
|
25
|
+
* Pure doppler playback-rate ratio for an emitter/listener pair. Returns 1 when
|
|
26
|
+
* both are stationary relative to each other; clamped to [0.25, 4].
|
|
27
|
+
*/
|
|
28
|
+
export declare function computeDopplerShift(emitterPosition: Vec3Like, emitterVelocity: Vec3Like, listenerPosition: Vec3Like, listenerVelocity: Vec3Like, options?: DopplerOptions): number;
|
|
29
|
+
/** Resolve an occlusion amount from a hook, a literal, or absence (clear). Always clamped to [0, 1]. */
|
|
30
|
+
export declare function resolveOcclusion(occlusion: OcclusionHook | number | undefined, emitter: Vec3Like, listener: Vec3Like): number;
|
|
31
|
+
/** Gain multiplier for an occlusion amount: fully blocked still leaks 15% (never fully silent). */
|
|
32
|
+
export declare function applyOcclusionToGain(amount: number): number;
|
|
33
|
+
/** Lowpass cutoff for an occlusion amount: clear = 20kHz, fully blocked ≈ 400Hz. */
|
|
34
|
+
export declare function occlusionLowpassFrequency(amount: number): number;
|
|
35
|
+
export interface PositionalEmitterOptions {
|
|
36
|
+
readonly context: AudioContextLike;
|
|
37
|
+
readonly destination?: AudioNode;
|
|
38
|
+
readonly clip?: AudioClip;
|
|
39
|
+
readonly volume?: number;
|
|
40
|
+
readonly loop?: boolean;
|
|
41
|
+
readonly position?: Vec3Like;
|
|
42
|
+
readonly velocity?: Vec3Like;
|
|
43
|
+
readonly attenuation?: DistanceAttenuationOptions;
|
|
44
|
+
readonly doppler?: DopplerOptions & {
|
|
45
|
+
readonly enabled?: boolean;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export interface PositionalEmitterEvidence {
|
|
49
|
+
readonly kind: "positional-emitter-evidence";
|
|
50
|
+
readonly position: Vec3Like;
|
|
51
|
+
readonly attenuationGain: number;
|
|
52
|
+
readonly dopplerShift: number;
|
|
53
|
+
readonly occlusion: number;
|
|
54
|
+
readonly state: AudioSourceState;
|
|
55
|
+
/** False when the context cannot build the panner/filter graph — math is still reported, never faked. */
|
|
56
|
+
readonly connected: boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A positional voice: `AudioSource` (clip + gain) → occlusion lowpass → `SpatialAudio`
|
|
60
|
+
* panner → bus. Reuses both owners instead of forking them; attenuation/doppler math
|
|
61
|
+
* is pure so evidence works headless.
|
|
62
|
+
*/
|
|
63
|
+
export declare class PositionalEmitter {
|
|
64
|
+
private readonly options;
|
|
65
|
+
readonly source: AudioSource;
|
|
66
|
+
readonly spatial: SpatialAudio | undefined;
|
|
67
|
+
private readonly filter;
|
|
68
|
+
private readonly baseVolume;
|
|
69
|
+
private positionRef;
|
|
70
|
+
private velocityRef;
|
|
71
|
+
private readonly attenuationOptions;
|
|
72
|
+
private readonly dopplerOptions;
|
|
73
|
+
private readonly dopplerEnabled;
|
|
74
|
+
private occlusionRef;
|
|
75
|
+
private lastAttenuation;
|
|
76
|
+
private lastDoppler;
|
|
77
|
+
constructor(options: PositionalEmitterOptions);
|
|
78
|
+
get position(): Vec3Like;
|
|
79
|
+
get occlusion(): number;
|
|
80
|
+
get connected(): boolean;
|
|
81
|
+
setPosition(position: Vec3Like): void;
|
|
82
|
+
setVelocity(velocity: Vec3Like): void;
|
|
83
|
+
setOcclusion(amount: number): void;
|
|
84
|
+
/**
|
|
85
|
+
* Recompute attenuation + doppler against the listener and push them into the
|
|
86
|
+
* live graph (gain, playback rate, filter). Pure math runs even when headless.
|
|
87
|
+
*/
|
|
88
|
+
update(listenerPosition: Vec3Like, listenerVelocity?: Vec3Like): PositionalEmitterEvidence;
|
|
89
|
+
play(when?: number): void;
|
|
90
|
+
stop(when?: number): void;
|
|
91
|
+
evidence(): PositionalEmitterEvidence;
|
|
92
|
+
dispose(): void;
|
|
93
|
+
private applyGain;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=PositionalEmitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PositionalEmitter.d.ts","sourceRoot":"","sources":["../../../../packages/audio/src/PositionalEmitter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { AudioSource } from "./AudioSource.js";
|
|
2
|
+
import { SpatialAudio } from "./SpatialAudio.js";
|
|
3
|
+
const SPEED_OF_SOUND_DEFAULT = 343;
|
|
4
|
+
const DOPPLER_MIN = 0.25;
|
|
5
|
+
const DOPPLER_MAX = 4;
|
|
6
|
+
/**
|
|
7
|
+
* Pure distance-attenuation gain in [0, 1], mirroring the PannerNode models so
|
|
8
|
+
* evidence stays meaningful even when no WebAudio context exists (headless runs).
|
|
9
|
+
*/
|
|
10
|
+
export function computeDistanceAttenuation(distance, options = {}) {
|
|
11
|
+
if (!Number.isFinite(distance) || distance < 0)
|
|
12
|
+
return 1;
|
|
13
|
+
const refDistance = Math.max(Number.EPSILON, options.refDistance ?? 1);
|
|
14
|
+
const maxDistance = Math.max(refDistance, options.maxDistance ?? 10_000);
|
|
15
|
+
const rolloff = Math.max(0, options.rolloffFactor ?? 1);
|
|
16
|
+
const model = options.model ?? "inverse";
|
|
17
|
+
if (distance <= refDistance)
|
|
18
|
+
return 1;
|
|
19
|
+
if (distance >= maxDistance)
|
|
20
|
+
return 0;
|
|
21
|
+
if (model === "linear") {
|
|
22
|
+
return Math.max(0, 1 - rolloff * ((distance - refDistance) / (maxDistance - refDistance)));
|
|
23
|
+
}
|
|
24
|
+
if (model === "exponential") {
|
|
25
|
+
return Math.pow(distance / refDistance, -rolloff);
|
|
26
|
+
}
|
|
27
|
+
return refDistance / (refDistance + rolloff * (distance - refDistance));
|
|
28
|
+
}
|
|
29
|
+
function dot(a, b) {
|
|
30
|
+
return a.x * b.x + a.y * b.y + a.z * b.z;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Pure doppler playback-rate ratio for an emitter/listener pair. Returns 1 when
|
|
34
|
+
* both are stationary relative to each other; clamped to [0.25, 4].
|
|
35
|
+
*/
|
|
36
|
+
export function computeDopplerShift(emitterPosition, emitterVelocity, listenerPosition, listenerVelocity, options = {}) {
|
|
37
|
+
const speedOfSound = options.speedOfSound ?? SPEED_OF_SOUND_DEFAULT;
|
|
38
|
+
const factor = options.dopplerFactor ?? 1;
|
|
39
|
+
if (!Number.isFinite(speedOfSound) || speedOfSound <= 0 || !Number.isFinite(factor) || factor < 0)
|
|
40
|
+
return 1;
|
|
41
|
+
const delta = {
|
|
42
|
+
x: emitterPosition.x - listenerPosition.x,
|
|
43
|
+
y: emitterPosition.y - listenerPosition.y,
|
|
44
|
+
z: emitterPosition.z - listenerPosition.z
|
|
45
|
+
};
|
|
46
|
+
const distance = Math.hypot(delta.x, delta.y, delta.z);
|
|
47
|
+
if (distance < Number.EPSILON)
|
|
48
|
+
return 1;
|
|
49
|
+
// `direction` points from listener to emitter. Closing velocities (movement that
|
|
50
|
+
// shrinks the distance) raise the observed pitch: f' = f(c + vl.r)/(c + ve.r).
|
|
51
|
+
const direction = { x: delta.x / distance, y: delta.y / distance, z: delta.z / distance };
|
|
52
|
+
const emitterRadial = dot(emitterVelocity, direction);
|
|
53
|
+
const listenerRadial = dot(listenerVelocity, direction);
|
|
54
|
+
const shift = (speedOfSound + factor * listenerRadial) / (speedOfSound + factor * emitterRadial);
|
|
55
|
+
if (!Number.isFinite(shift))
|
|
56
|
+
return 1;
|
|
57
|
+
return Math.min(DOPPLER_MAX, Math.max(DOPPLER_MIN, shift));
|
|
58
|
+
}
|
|
59
|
+
/** Resolve an occlusion amount from a hook, a literal, or absence (clear). Always clamped to [0, 1]. */
|
|
60
|
+
export function resolveOcclusion(occlusion, emitter, listener) {
|
|
61
|
+
if (occlusion === undefined)
|
|
62
|
+
return 0;
|
|
63
|
+
const raw = typeof occlusion === "function" ? occlusion(emitter, listener) : occlusion;
|
|
64
|
+
if (!Number.isFinite(raw))
|
|
65
|
+
return 0;
|
|
66
|
+
return Math.min(1, Math.max(0, raw));
|
|
67
|
+
}
|
|
68
|
+
/** Gain multiplier for an occlusion amount: fully blocked still leaks 15% (never fully silent). */
|
|
69
|
+
export function applyOcclusionToGain(amount) {
|
|
70
|
+
const clamped = Math.min(1, Math.max(0, amount));
|
|
71
|
+
return 1 - 0.85 * clamped;
|
|
72
|
+
}
|
|
73
|
+
/** Lowpass cutoff for an occlusion amount: clear = 20kHz, fully blocked ≈ 400Hz. */
|
|
74
|
+
export function occlusionLowpassFrequency(amount) {
|
|
75
|
+
const clamped = Math.min(1, Math.max(0, amount));
|
|
76
|
+
return 20_000 * Math.pow(400 / 20_000, clamped);
|
|
77
|
+
}
|
|
78
|
+
const ZERO_VELOCITY = { x: 0, y: 0, z: 0 };
|
|
79
|
+
/**
|
|
80
|
+
* A positional voice: `AudioSource` (clip + gain) → occlusion lowpass → `SpatialAudio`
|
|
81
|
+
* panner → bus. Reuses both owners instead of forking them; attenuation/doppler math
|
|
82
|
+
* is pure so evidence works headless.
|
|
83
|
+
*/
|
|
84
|
+
export class PositionalEmitter {
|
|
85
|
+
options;
|
|
86
|
+
source;
|
|
87
|
+
spatial;
|
|
88
|
+
filter;
|
|
89
|
+
baseVolume;
|
|
90
|
+
positionRef;
|
|
91
|
+
velocityRef;
|
|
92
|
+
attenuationOptions;
|
|
93
|
+
dopplerOptions;
|
|
94
|
+
dopplerEnabled;
|
|
95
|
+
occlusionRef = 0;
|
|
96
|
+
lastAttenuation = 1;
|
|
97
|
+
lastDoppler = 1;
|
|
98
|
+
constructor(options) {
|
|
99
|
+
this.options = options;
|
|
100
|
+
this.baseVolume = options.volume ?? 1;
|
|
101
|
+
this.positionRef = { ...(options.position ?? { x: 0, y: 0, z: 0 }) };
|
|
102
|
+
this.velocityRef = { ...(options.velocity ?? ZERO_VELOCITY) };
|
|
103
|
+
this.attenuationOptions = { ...(options.attenuation ?? {}) };
|
|
104
|
+
this.dopplerOptions = { ...(options.doppler ?? {}) };
|
|
105
|
+
this.dopplerEnabled = options.doppler?.enabled ?? true;
|
|
106
|
+
let spatial;
|
|
107
|
+
let filter;
|
|
108
|
+
try {
|
|
109
|
+
spatial = new SpatialAudio({
|
|
110
|
+
context: options.context,
|
|
111
|
+
destination: options.destination,
|
|
112
|
+
position: this.positionRef,
|
|
113
|
+
maxDistance: this.attenuationOptions.maxDistance,
|
|
114
|
+
refDistance: this.attenuationOptions.refDistance,
|
|
115
|
+
rolloffFactor: this.attenuationOptions.rolloffFactor
|
|
116
|
+
});
|
|
117
|
+
filter = options.context.createBiquadFilter();
|
|
118
|
+
filter.type = "lowpass";
|
|
119
|
+
filter.frequency.value = 20_000;
|
|
120
|
+
filter.connect(spatial.panner);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
spatial = undefined;
|
|
124
|
+
filter = undefined;
|
|
125
|
+
}
|
|
126
|
+
this.spatial = spatial;
|
|
127
|
+
this.filter = filter;
|
|
128
|
+
this.source = new AudioSource({
|
|
129
|
+
context: options.context,
|
|
130
|
+
destination: filter ?? spatial?.panner ?? options.destination,
|
|
131
|
+
clip: options.clip,
|
|
132
|
+
loop: options.loop,
|
|
133
|
+
volume: this.baseVolume
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
get position() {
|
|
137
|
+
return { ...this.positionRef };
|
|
138
|
+
}
|
|
139
|
+
get occlusion() {
|
|
140
|
+
return this.occlusionRef;
|
|
141
|
+
}
|
|
142
|
+
get connected() {
|
|
143
|
+
return this.spatial !== undefined && this.filter !== undefined;
|
|
144
|
+
}
|
|
145
|
+
setPosition(position) {
|
|
146
|
+
this.positionRef = { ...position };
|
|
147
|
+
this.spatial?.setPosition(position);
|
|
148
|
+
}
|
|
149
|
+
setVelocity(velocity) {
|
|
150
|
+
this.velocityRef = { ...velocity };
|
|
151
|
+
}
|
|
152
|
+
setOcclusion(amount) {
|
|
153
|
+
this.occlusionRef = Math.min(1, Math.max(0, amount));
|
|
154
|
+
if (this.filter) {
|
|
155
|
+
this.filter.frequency.value = occlusionLowpassFrequency(this.occlusionRef);
|
|
156
|
+
}
|
|
157
|
+
this.applyGain();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Recompute attenuation + doppler against the listener and push them into the
|
|
161
|
+
* live graph (gain, playback rate, filter). Pure math runs even when headless.
|
|
162
|
+
*/
|
|
163
|
+
update(listenerPosition, listenerVelocity = ZERO_VELOCITY) {
|
|
164
|
+
const distance = Math.hypot(this.positionRef.x - listenerPosition.x, this.positionRef.y - listenerPosition.y, this.positionRef.z - listenerPosition.z);
|
|
165
|
+
this.lastAttenuation = computeDistanceAttenuation(distance, this.attenuationOptions);
|
|
166
|
+
this.lastDoppler = this.dopplerEnabled
|
|
167
|
+
? computeDopplerShift(this.positionRef, this.velocityRef, listenerPosition, listenerVelocity, this.dopplerOptions)
|
|
168
|
+
: 1;
|
|
169
|
+
this.source.playbackRate = this.lastDoppler;
|
|
170
|
+
this.applyGain();
|
|
171
|
+
return this.evidence();
|
|
172
|
+
}
|
|
173
|
+
play(when = 0) {
|
|
174
|
+
this.source.play(when);
|
|
175
|
+
}
|
|
176
|
+
stop(when = 0) {
|
|
177
|
+
this.source.stop(when);
|
|
178
|
+
}
|
|
179
|
+
evidence() {
|
|
180
|
+
return {
|
|
181
|
+
kind: "positional-emitter-evidence",
|
|
182
|
+
position: { ...this.positionRef },
|
|
183
|
+
attenuationGain: this.lastAttenuation,
|
|
184
|
+
dopplerShift: this.lastDoppler,
|
|
185
|
+
occlusion: this.occlusionRef,
|
|
186
|
+
state: this.source.state,
|
|
187
|
+
connected: this.connected
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
dispose() {
|
|
191
|
+
this.source.dispose();
|
|
192
|
+
this.filter?.disconnect();
|
|
193
|
+
this.spatial?.dispose();
|
|
194
|
+
}
|
|
195
|
+
applyGain() {
|
|
196
|
+
this.source.setVolume(this.baseVolume * this.lastAttenuation * applyOcclusionToGain(this.occlusionRef));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=PositionalEmitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PositionalEmitter.js","sourceRoot":"","sources":["../../../../packages/audio/src/PositionalEmitter.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,12 @@ export { AudioMixer, createAudioMixerEvidence, createAnimationAudioMixer } from
|
|
|
16
16
|
export type { AudioMixerBusEvidence, AudioMixerEvidence, AnimationAudioMixer, AnimationAudioMixerOptions } from "./AudioMixer.js";
|
|
17
17
|
export { AudioSource } from "./AudioSource.js";
|
|
18
18
|
export type { AudioSourceOptions, AudioSourceState } from "./AudioSource.js";
|
|
19
|
+
export { PositionalEmitter, applyOcclusionToGain, computeDistanceAttenuation, computeDopplerShift, occlusionLowpassFrequency, resolveOcclusion } from "./PositionalEmitter.js";
|
|
20
|
+
export type { DistanceAttenuationModel, DistanceAttenuationOptions, DopplerOptions, OcclusionHook, PositionalEmitterEvidence, PositionalEmitterOptions } from "./PositionalEmitter.js";
|
|
21
|
+
export { attachFocusPolicy, createGameMixer, focusHandlersForMixer } from "./GameMixer.js";
|
|
22
|
+
export type { FocusEventTargetLike, FocusMutePolicy, FocusPolicyHandlers, GameMixer, GameMixerBusLevel, GameMixerEvidence, GameMixerOptions } from "./GameMixer.js";
|
|
23
|
+
export { FootstepPlayer } from "./Footsteps.js";
|
|
24
|
+
export type { FootId, FootPlantEvent, FootstepEvidence, FootstepPlayerOptions } from "./Footsteps.js";
|
|
19
25
|
export { AudioSystem } from "./AudioSystem.js";
|
|
20
26
|
export { SceneAudioBridge } from "./SceneAudioBridge.js";
|
|
21
27
|
export type { SceneAudioSourceBinding } from "./SceneAudioBridge.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/audio/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAClF,YAAY,EACV,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,EAC1B,4BAA4B,EAC5B,kBAAkB,EAClB,0BAA0B,EAC1B,cAAc,EACd,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,8BAA8B,EAAE,8BAA8B,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACpJ,YAAY,EACV,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACjK,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,uBAAuB,EACvB,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC7G,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAC/F,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/H,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/audio/src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,9 @@ export { AudioContextManager } from "./AudioContextManager.js";
|
|
|
7
7
|
export { AudioListener } from "./AudioListener.js";
|
|
8
8
|
export { AudioMixer, createAudioMixerEvidence, createAnimationAudioMixer } from "./AudioMixer.js";
|
|
9
9
|
export { AudioSource } from "./AudioSource.js";
|
|
10
|
+
export { PositionalEmitter, applyOcclusionToGain, computeDistanceAttenuation, computeDopplerShift, occlusionLowpassFrequency, resolveOcclusion } from "./PositionalEmitter.js";
|
|
11
|
+
export { attachFocusPolicy, createGameMixer, focusHandlersForMixer } from "./GameMixer.js";
|
|
12
|
+
export { FootstepPlayer } from "./Footsteps.js";
|
|
10
13
|
export { AudioSystem } from "./AudioSystem.js";
|
|
11
14
|
export { SceneAudioBridge } from "./SceneAudioBridge.js";
|
|
12
15
|
export { SpatialAudio } from "./SpatialAudio.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/audio/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAclF,OAAO,EAAE,8BAA8B,EAAE,8BAA8B,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAepJ,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAYjK,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAE/F,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/audio/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAclF,OAAO,EAAE,8BAA8B,EAAE,8BAA8B,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAepJ,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAYjK,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAE/F,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,EACnB,yBAAyB,EACzB,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAS7B,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAUxF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aura3d/audio",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"main": "./dist/index.js",
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@aura3d/scene": "
|
|
14
|
+
"@aura3d/scene": "3.0.0"
|
|
15
15
|
},
|
|
16
16
|
"description": "Browser audio lifecycle, clips, sources, buses, mixing, listener transforms, spatial attenuation, effects, and scene audio bridges for Aura3D.",
|
|
17
17
|
"keywords": [
|