@aura3d/audio 1.0.6

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.
Files changed (84) hide show
  1. package/README.md +16 -0
  2. package/dist/AdaptiveMusicFixtures.d.ts +36 -0
  3. package/dist/AdaptiveMusicFixtures.d.ts.map +1 -0
  4. package/dist/AdaptiveMusicFixtures.js +90 -0
  5. package/dist/AdaptiveMusicFixtures.js.map +1 -0
  6. package/dist/AudioBus.d.ts +13 -0
  7. package/dist/AudioBus.d.ts.map +1 -0
  8. package/dist/AudioBus.js +32 -0
  9. package/dist/AudioBus.js.map +1 -0
  10. package/dist/AudioClip.d.ts +13 -0
  11. package/dist/AudioClip.d.ts.map +1 -0
  12. package/dist/AudioClip.js +18 -0
  13. package/dist/AudioClip.js.map +1 -0
  14. package/dist/AudioContextManager.d.ts +31 -0
  15. package/dist/AudioContextManager.d.ts.map +1 -0
  16. package/dist/AudioContextManager.js +49 -0
  17. package/dist/AudioContextManager.js.map +1 -0
  18. package/dist/AudioEffect.d.ts +8 -0
  19. package/dist/AudioEffect.d.ts.map +1 -0
  20. package/dist/AudioEffect.js +2 -0
  21. package/dist/AudioEffect.js.map +1 -0
  22. package/dist/AudioEffectsAnalysisFixtures.d.ts +99 -0
  23. package/dist/AudioEffectsAnalysisFixtures.d.ts.map +1 -0
  24. package/dist/AudioEffectsAnalysisFixtures.js +192 -0
  25. package/dist/AudioEffectsAnalysisFixtures.js.map +1 -0
  26. package/dist/AudioListener.d.ts +12 -0
  27. package/dist/AudioListener.d.ts.map +1 -0
  28. package/dist/AudioListener.js +11 -0
  29. package/dist/AudioListener.js.map +1 -0
  30. package/dist/AudioMixer.d.ts +12 -0
  31. package/dist/AudioMixer.d.ts.map +1 -0
  32. package/dist/AudioMixer.js +33 -0
  33. package/dist/AudioMixer.js.map +1 -0
  34. package/dist/AudioSource.d.ts +25 -0
  35. package/dist/AudioSource.d.ts.map +1 -0
  36. package/dist/AudioSource.js +58 -0
  37. package/dist/AudioSource.js.map +1 -0
  38. package/dist/AudioSystem.d.ts +13 -0
  39. package/dist/AudioSystem.d.ts.map +1 -0
  40. package/dist/AudioSystem.js +28 -0
  41. package/dist/AudioSystem.js.map +1 -0
  42. package/dist/SceneAudioBridge.d.ts +19 -0
  43. package/dist/SceneAudioBridge.d.ts.map +1 -0
  44. package/dist/SceneAudioBridge.js +37 -0
  45. package/dist/SceneAudioBridge.js.map +1 -0
  46. package/dist/SpatialAudio.d.ts +17 -0
  47. package/dist/SpatialAudio.d.ts.map +1 -0
  48. package/dist/SpatialAudio.js +22 -0
  49. package/dist/SpatialAudio.js.map +1 -0
  50. package/dist/SpatialAudioFixtures.d.ts +38 -0
  51. package/dist/SpatialAudioFixtures.d.ts.map +1 -0
  52. package/dist/SpatialAudioFixtures.js +94 -0
  53. package/dist/SpatialAudioFixtures.js.map +1 -0
  54. package/dist/effects/Filter.d.ts +13 -0
  55. package/dist/effects/Filter.d.ts.map +1 -0
  56. package/dist/effects/Filter.js +31 -0
  57. package/dist/effects/Filter.js.map +1 -0
  58. package/dist/effects/Reverb.d.ts +12 -0
  59. package/dist/effects/Reverb.d.ts.map +1 -0
  60. package/dist/effects/Reverb.js +23 -0
  61. package/dist/effects/Reverb.js.map +1 -0
  62. package/dist/index.d.ts +25 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +15 -0
  65. package/dist/index.js.map +1 -0
  66. package/package.json +16 -0
  67. package/src/AdaptiveMusicFixtures.ts +132 -0
  68. package/src/AudioBus.ts +39 -0
  69. package/src/AudioClip.ts +26 -0
  70. package/src/AudioContextManager.ts +74 -0
  71. package/src/AudioEffect.ts +7 -0
  72. package/src/AudioEffectsAnalysisFixtures.ts +311 -0
  73. package/src/AudioListener.ts +17 -0
  74. package/src/AudioMixer.ts +36 -0
  75. package/src/AudioSource.ts +75 -0
  76. package/src/AudioSystem.ts +34 -0
  77. package/src/SceneAudioBridge.ts +49 -0
  78. package/src/SpatialAudio.ts +36 -0
  79. package/src/SpatialAudioFixtures.ts +137 -0
  80. package/src/effects/Filter.ts +39 -0
  81. package/src/effects/Reverb.ts +30 -0
  82. package/src/index.ts +33 -0
  83. package/tests/audio.test.ts +121 -0
  84. package/tsconfig.json +7 -0
@@ -0,0 +1,94 @@
1
+ const OCCLUSION = {
2
+ none: { lowpassHz: 20_000, volume: 1 },
3
+ light: { lowpassHz: 8_000, volume: 0.9 },
4
+ medium: { lowpassHz: 3_000, volume: 0.7 },
5
+ heavy: { lowpassHz: 800, volume: 0.4 },
6
+ complete: { lowpassHz: 200, volume: 0.1 }
7
+ };
8
+ export function sampleAudioEnvironmentFixture(options = {}) {
9
+ const sourcePosition = options.sourcePosition ?? [0.85, 0.15, 0];
10
+ const listenerPosition = options.listenerPosition ?? [0, 0, 3];
11
+ const sourceVelocity = options.sourceVelocity ?? [-2.5, 0.2, 0];
12
+ const listenerVelocity = options.listenerVelocity ?? [0.7, 0, 0];
13
+ const obstacleCount = Math.max(0, Math.floor(options.obstacleCount ?? 2));
14
+ const distance = vectorLength(sub(sourcePosition, listenerPosition));
15
+ const direction = normalize(sub(listenerPosition, sourcePosition));
16
+ const relativeVelocity = dot(sub(sourceVelocity, listenerVelocity), direction);
17
+ const approaching = relativeVelocity > 0;
18
+ const speedOfSound = 343;
19
+ const pitchFactor = clamp(speedOfSound / Math.max(1, speedOfSound - relativeVelocity), 0.5, 2);
20
+ const baseFrequencyHz = options.baseFrequencyHz ?? 440;
21
+ const level = occlusionLevel(obstacleCount);
22
+ const occlusion = OCCLUSION[level];
23
+ const zoneRadius = Math.max(0.001, options.reverbZoneRadius ?? 8);
24
+ const zoneDistance = Math.max(0, options.reverbZoneDistance ?? distance);
25
+ const blend = clamp(1 - zoneDistance / zoneRadius, 0, 1);
26
+ const fixture = {
27
+ source: "origin-master-spatial-audio-environment-adapted",
28
+ distance: round(distance),
29
+ occlusion: {
30
+ level,
31
+ obstacleCount,
32
+ lowpassHz: occlusion.lowpassHz,
33
+ volume: occlusion.volume
34
+ },
35
+ doppler: {
36
+ relativeVelocity: round(relativeVelocity),
37
+ approaching,
38
+ pitchFactor: round(pitchFactor),
39
+ frequencyShiftHz: round(baseFrequencyHz * (pitchFactor - 1))
40
+ },
41
+ reverb: {
42
+ zoneRadius: round(zoneRadius),
43
+ zoneDistance: round(zoneDistance),
44
+ blend: round(blend),
45
+ wetLevel: round(0.55 * blend),
46
+ dryLevel: round(0.85 * (1 - blend * 0.5))
47
+ },
48
+ hash: "",
49
+ claimBoundary: "Spatial audio environment fixture adapts old occlusion, doppler, and reverb-zone math for deterministic telemetry; it does not implement authored audio middleware or Unity/Unreal acoustic parity."
50
+ };
51
+ return {
52
+ ...fixture,
53
+ hash: stableHash(`${fixture.distance}|${fixture.occlusion.level}|${fixture.occlusion.obstacleCount}|${fixture.doppler.pitchFactor}|${fixture.reverb.blend}`)
54
+ };
55
+ }
56
+ function occlusionLevel(obstacleCount) {
57
+ if (obstacleCount <= 0)
58
+ return "none";
59
+ if (obstacleCount === 1)
60
+ return "light";
61
+ if (obstacleCount === 2)
62
+ return "medium";
63
+ if (obstacleCount === 3)
64
+ return "heavy";
65
+ return "complete";
66
+ }
67
+ function sub(left, right) {
68
+ return [left[0] - right[0], left[1] - right[1], left[2] - right[2]];
69
+ }
70
+ function dot(left, right) {
71
+ return left[0] * right[0] + left[1] * right[1] + left[2] * right[2];
72
+ }
73
+ function normalize(value) {
74
+ const length = vectorLength(value);
75
+ return length > 0 ? [value[0] / length, value[1] / length, value[2] / length] : [0, 0, 0];
76
+ }
77
+ function vectorLength(value) {
78
+ return Math.hypot(value[0], value[1], value[2]);
79
+ }
80
+ function clamp(value, min, max) {
81
+ return Math.max(min, Math.min(max, Number.isFinite(value) ? value : min));
82
+ }
83
+ function round(value) {
84
+ return Number(value.toFixed(4));
85
+ }
86
+ function stableHash(value) {
87
+ let hash = 0x811c9dc5;
88
+ for (let index = 0; index < value.length; index += 1) {
89
+ hash ^= value.charCodeAt(index);
90
+ hash = Math.imul(hash, 0x01000193);
91
+ }
92
+ return (hash >>> 0).toString(16).padStart(8, "0");
93
+ }
94
+ //# sourceMappingURL=SpatialAudioFixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpatialAudioFixtures.js","sourceRoot":"","sources":["../../../../packages/audio/src/SpatialAudioFixtures.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { AudioContextLike } from "../AudioContextManager";
2
+ import type { AudioEffect } from "../AudioEffect";
3
+ export declare class FilterEffect implements AudioEffect {
4
+ readonly input: BiquadFilterNode;
5
+ readonly output: BiquadFilterNode;
6
+ constructor(context: AudioContextLike, type?: BiquadFilterType);
7
+ setFrequency(value: number): void;
8
+ setQ(value: number): void;
9
+ connect(destination: AudioNode): AudioNode;
10
+ disconnect(): void;
11
+ dispose(): void;
12
+ }
13
+ //# sourceMappingURL=Filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Filter.d.ts","sourceRoot":"","sources":["../../../../../packages/audio/src/effects/Filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,qBAAa,YAAa,YAAW,WAAW;IAC9C,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;gBAEtB,OAAO,EAAE,gBAAgB,EAAE,IAAI,GAAE,gBAA4B;IAMzE,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOjC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOzB,OAAO,CAAC,WAAW,EAAE,SAAS,GAAG,SAAS;IAI1C,UAAU,IAAI,IAAI;IAIlB,OAAO,IAAI,IAAI;CAGhB"}
@@ -0,0 +1,31 @@
1
+ export class FilterEffect {
2
+ input;
3
+ output;
4
+ constructor(context, type = "lowpass") {
5
+ this.input = context.createBiquadFilter();
6
+ this.input.type = type;
7
+ this.output = this.input;
8
+ }
9
+ setFrequency(value) {
10
+ if (!Number.isFinite(value) || value <= 0) {
11
+ throw new Error("Filter frequency must be positive");
12
+ }
13
+ this.input.frequency.value = value;
14
+ }
15
+ setQ(value) {
16
+ if (!Number.isFinite(value) || value < 0) {
17
+ throw new Error("Filter Q must be non-negative");
18
+ }
19
+ this.input.Q.value = value;
20
+ }
21
+ connect(destination) {
22
+ return this.output.connect(destination);
23
+ }
24
+ disconnect() {
25
+ this.output.disconnect();
26
+ }
27
+ dispose() {
28
+ this.disconnect();
29
+ }
30
+ }
31
+ //# sourceMappingURL=Filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Filter.js","sourceRoot":"","sources":["../../../../../packages/audio/src/effects/Filter.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,YAAY;IACd,KAAK,CAAmB;IACxB,MAAM,CAAmB;IAElC,YAAY,OAAyB,EAAE,OAAyB,SAAS;QACvE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;IAC3B,CAAC;IAED,YAAY,CAAC,KAAa;QACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC;IACrC,CAAC;IAED,IAAI,CAAC,KAAa;QAChB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC;IAC7B,CAAC;IAED,OAAO,CAAC,WAAsB;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAED,UAAU;QACR,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO;QACL,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import type { AudioContextLike } from "../AudioContextManager";
2
+ import type { AudioEffect } from "../AudioEffect";
3
+ export declare class ReverbEffect implements AudioEffect {
4
+ readonly input: ConvolverNode;
5
+ readonly output: ConvolverNode;
6
+ constructor(context: AudioContextLike, impulse?: AudioBuffer);
7
+ setImpulse(buffer: AudioBuffer): void;
8
+ connect(destination: AudioNode): AudioNode;
9
+ disconnect(): void;
10
+ dispose(): void;
11
+ }
12
+ //# sourceMappingURL=Reverb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Reverb.d.ts","sourceRoot":"","sources":["../../../../../packages/audio/src/effects/Reverb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,qBAAa,YAAa,YAAW,WAAW;IAC9C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;gBAEnB,OAAO,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,WAAW;IAM5D,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAIrC,OAAO,CAAC,WAAW,EAAE,SAAS,GAAG,SAAS;IAI1C,UAAU,IAAI,IAAI;IAIlB,OAAO,IAAI,IAAI;CAIhB"}
@@ -0,0 +1,23 @@
1
+ export class ReverbEffect {
2
+ input;
3
+ output;
4
+ constructor(context, impulse) {
5
+ this.input = context.createConvolver();
6
+ this.input.buffer = impulse ?? null;
7
+ this.output = this.input;
8
+ }
9
+ setImpulse(buffer) {
10
+ this.input.buffer = buffer;
11
+ }
12
+ connect(destination) {
13
+ return this.output.connect(destination);
14
+ }
15
+ disconnect() {
16
+ this.output.disconnect();
17
+ }
18
+ dispose() {
19
+ this.input.buffer = null;
20
+ this.disconnect();
21
+ }
22
+ }
23
+ //# sourceMappingURL=Reverb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Reverb.js","sourceRoot":"","sources":["../../../../../packages/audio/src/effects/Reverb.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,YAAY;IACd,KAAK,CAAgB;IACrB,MAAM,CAAgB;IAE/B,YAAY,OAAyB,EAAE,OAAqB;QAC1D,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,IAAI,IAAI,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;IAC3B,CAAC;IAED,UAAU,CAAC,MAAmB;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IAC7B,CAAC;IAED,OAAO,CAAC,WAAsB;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAED,UAAU;QACR,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO;QACL,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ export { AudioBus } from "./AudioBus";
2
+ export { AudioClip } from "./AudioClip";
3
+ export type { AudioClipOptions } from "./AudioClip";
4
+ export { sampleAudioEffectsAnalysisFixture } from "./AudioEffectsAnalysisFixtures";
5
+ export type { AudioChorusPreset, AudioCompressorPreset, AudioDelayPreset, AudioDistortionCurve, AudioEffectsAnalysisFixture, AudioEffectsAnalysisFixtureOptions, AudioEqBandFixture, AudioSpectrumBandFixture } from "./AudioEffectsAnalysisFixtures";
6
+ export { sampleAdaptiveMusicFixture } from "./AdaptiveMusicFixtures";
7
+ export type { AdaptiveMusicCrossfadeCurve, AdaptiveMusicFixture, AdaptiveMusicFixtureOptions, AdaptiveMusicFixtureState, AdaptiveMusicLayerMix } from "./AdaptiveMusicFixtures";
8
+ export { sampleAudioEnvironmentFixture } from "./SpatialAudioFixtures";
9
+ export type { AudioEnvironmentFixture, AudioEnvironmentFixtureOptions, AudioOcclusionLevel } from "./SpatialAudioFixtures";
10
+ export { AudioContextManager } from "./AudioContextManager";
11
+ export type { AudioContextLike, AudioContextManagerOptions, AudioContextState } from "./AudioContextManager";
12
+ export type { AudioEffect } from "./AudioEffect";
13
+ export { AudioListener } from "./AudioListener";
14
+ export type { Vec3Like } from "./AudioListener";
15
+ export { AudioMixer } from "./AudioMixer";
16
+ export { AudioSource } from "./AudioSource";
17
+ export type { AudioSourceOptions, AudioSourceState } from "./AudioSource";
18
+ export { AudioSystem } from "./AudioSystem";
19
+ export { SceneAudioBridge } from "./SceneAudioBridge";
20
+ export type { SceneAudioSourceBinding } from "./SceneAudioBridge";
21
+ export { SpatialAudio } from "./SpatialAudio";
22
+ export type { SpatialAudioOptions } from "./SpatialAudio";
23
+ export { FilterEffect } from "./effects/Filter";
24
+ export { ReverbEffect } from "./effects/Reverb";
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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,iCAAiC,EAAE,MAAM,gCAAgC,CAAC;AACnF,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,EAC3B,kCAAkC,EAClC,kBAAkB,EAClB,wBAAwB,EACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,YAAY,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChL,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AACvE,YAAY,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC3H,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,MAAM,cAAc,CAAC;AAC1C,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"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ export { AudioBus } from "./AudioBus.js";
2
+ export { AudioClip } from "./AudioClip.js";
3
+ export { sampleAudioEffectsAnalysisFixture } from "./AudioEffectsAnalysisFixtures.js";
4
+ export { sampleAdaptiveMusicFixture } from "./AdaptiveMusicFixtures.js";
5
+ export { sampleAudioEnvironmentFixture } from "./SpatialAudioFixtures.js";
6
+ export { AudioContextManager } from "./AudioContextManager.js";
7
+ export { AudioListener } from "./AudioListener.js";
8
+ export { AudioMixer } from "./AudioMixer.js";
9
+ export { AudioSource } from "./AudioSource.js";
10
+ export { AudioSystem } from "./AudioSystem.js";
11
+ export { SceneAudioBridge } from "./SceneAudioBridge.js";
12
+ export { SpatialAudio } from "./SpatialAudio.js";
13
+ export { FilterEffect } from "./effects/Filter.js";
14
+ export { ReverbEffect } from "./effects/Reverb.js";
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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,iCAAiC,EAAE,MAAM,gCAAgC,CAAC;AAWnF,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAErE,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,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"}
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@aura3d/audio",
3
+ "version": "1.0.6",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "import": "./dist/index.js"
9
+ }
10
+ },
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "dependencies": {
14
+ "@aura3d/scene": "1.0.6"
15
+ }
16
+ }
@@ -0,0 +1,132 @@
1
+ export type AdaptiveMusicFixtureState = "calm" | "tension" | "action" | "victory" | "defeat";
2
+
3
+ export type AdaptiveMusicCrossfadeCurve = "linear" | "equal-power" | "s-curve";
4
+
5
+ export interface AdaptiveMusicFixtureOptions {
6
+ readonly state?: AdaptiveMusicFixtureState;
7
+ readonly intensity?: number;
8
+ readonly curve?: AdaptiveMusicCrossfadeCurve;
9
+ }
10
+
11
+ export interface AdaptiveMusicLayerMix {
12
+ readonly id: string;
13
+ readonly role: "bed" | "pulse" | "lead" | "stinger";
14
+ readonly threshold: number;
15
+ readonly baseVolume: number;
16
+ readonly targetVolume: number;
17
+ readonly enabled: boolean;
18
+ }
19
+
20
+ export interface AdaptiveMusicFixture {
21
+ readonly source: "origin-master-adaptive-music-adapted";
22
+ readonly state: AdaptiveMusicFixtureState;
23
+ readonly intensity: number;
24
+ readonly curve: AdaptiveMusicCrossfadeCurve;
25
+ readonly transitionSeconds: number;
26
+ readonly loopBars: number;
27
+ readonly tempoBpm: number;
28
+ readonly layers: readonly AdaptiveMusicLayerMix[];
29
+ readonly activeLayerCount: number;
30
+ readonly peakLayerVolume: number;
31
+ readonly crossfade: {
32
+ readonly outGain: readonly number[];
33
+ readonly inGain: readonly number[];
34
+ readonly equalPowerNormalized: boolean;
35
+ };
36
+ readonly hash: string;
37
+ readonly claimBoundary: string;
38
+ }
39
+
40
+ const STATE_INTENSITY: Record<AdaptiveMusicFixtureState, number> = {
41
+ calm: 0.05,
42
+ tension: 0.42,
43
+ action: 0.82,
44
+ victory: 0.58,
45
+ defeat: 0.22
46
+ };
47
+
48
+ const LAYERS: readonly Omit<AdaptiveMusicLayerMix, "targetVolume" | "enabled">[] = [
49
+ { id: "ambient-bed", role: "bed", threshold: 0, baseVolume: 0.46 },
50
+ { id: "rhythm-pulse", role: "pulse", threshold: 0.32, baseVolume: 0.7 },
51
+ { id: "lead-motif", role: "lead", threshold: 0.62, baseVolume: 0.58 },
52
+ { id: "result-stinger", role: "stinger", threshold: 0.52, baseVolume: 0.84 }
53
+ ];
54
+
55
+ export function sampleAdaptiveMusicFixture(options: AdaptiveMusicFixtureOptions = {}): AdaptiveMusicFixture {
56
+ const state = options.state ?? "tension";
57
+ const intensity = clamp01(options.intensity ?? STATE_INTENSITY[state]);
58
+ const curve = options.curve ?? "equal-power";
59
+ const layers = LAYERS.map((layer) => {
60
+ const enabled = layer.role === "stinger" ? state === "victory" || state === "defeat" : intensity >= layer.threshold;
61
+ const ramp = layer.threshold >= 1 ? 0 : clamp01((intensity - layer.threshold) / Math.max(0.08, 1 - layer.threshold));
62
+ const stateBoost = layer.role === "stinger" && state === "victory" ? 1 : layer.role === "stinger" && state === "defeat" ? 0.62 : 1;
63
+ return {
64
+ ...layer,
65
+ enabled,
66
+ targetVolume: enabled ? round(layer.baseVolume * Math.max(layer.role === "bed" ? 0.45 : 0.18, ramp) * stateBoost) : 0
67
+ };
68
+ });
69
+ const crossfade = crossfadeSamples(curve, 6);
70
+ const hash = stableHash([
71
+ state,
72
+ intensity.toFixed(4),
73
+ curve,
74
+ ...layers.map((layer) => `${layer.id}:${layer.targetVolume.toFixed(4)}:${layer.enabled ? 1 : 0}`)
75
+ ].join("|"));
76
+ return {
77
+ source: "origin-master-adaptive-music-adapted",
78
+ state,
79
+ intensity: round(intensity),
80
+ curve,
81
+ transitionSeconds: state === "victory" || state === "defeat" ? 0.65 : 1.4,
82
+ loopBars: 8,
83
+ tempoBpm: state === "action" ? 138 : state === "victory" ? 124 : 112,
84
+ layers,
85
+ activeLayerCount: layers.filter((layer) => layer.enabled && layer.targetVolume > 0).length,
86
+ peakLayerVolume: round(Math.max(...layers.map((layer) => layer.targetVolume))),
87
+ crossfade,
88
+ hash,
89
+ claimBoundary: "Adaptive music fixture adapts old layer/crossfade state for deterministic runtime evidence; it does not play authored stems or prove Unity/Unreal audio middleware parity."
90
+ };
91
+ }
92
+
93
+ function crossfadeSamples(curve: AdaptiveMusicCrossfadeCurve, steps: number): AdaptiveMusicFixture["crossfade"] {
94
+ const outGain: number[] = [];
95
+ const inGain: number[] = [];
96
+ for (let index = 0; index <= steps; index += 1) {
97
+ const t = index / steps;
98
+ if (curve === "equal-power") {
99
+ outGain.push(round(Math.cos(t * Math.PI * 0.5)));
100
+ inGain.push(round(Math.sin(t * Math.PI * 0.5)));
101
+ } else if (curve === "s-curve") {
102
+ const s = (Math.sin((t - 0.5) * Math.PI) + 1) / 2;
103
+ outGain.push(round(1 - s));
104
+ inGain.push(round(s));
105
+ } else {
106
+ outGain.push(round(1 - t));
107
+ inGain.push(round(t));
108
+ }
109
+ }
110
+ return {
111
+ outGain,
112
+ inGain,
113
+ equalPowerNormalized: curve === "equal-power" && outGain.every((out, index) => Math.abs(out * out + (inGain[index] ?? 0) * (inGain[index] ?? 0) - 1) < 0.002)
114
+ };
115
+ }
116
+
117
+ function stableHash(value: string): string {
118
+ let hash = 0x811c9dc5;
119
+ for (let index = 0; index < value.length; index += 1) {
120
+ hash ^= value.charCodeAt(index);
121
+ hash = Math.imul(hash, 0x01000193);
122
+ }
123
+ return (hash >>> 0).toString(16).padStart(8, "0");
124
+ }
125
+
126
+ function clamp01(value: number): number {
127
+ return Number.isFinite(value) ? Math.max(0, Math.min(1, value)) : 0;
128
+ }
129
+
130
+ function round(value: number): number {
131
+ return Number(value.toFixed(4));
132
+ }
@@ -0,0 +1,39 @@
1
+ import type { AudioContextLike } from "./AudioContextManager";
2
+
3
+ export class AudioBus {
4
+ readonly input: GainNode;
5
+ readonly output: GainNode;
6
+ private muted = false;
7
+ private storedVolume = 1;
8
+
9
+ constructor(
10
+ readonly name: string,
11
+ context: AudioContextLike,
12
+ destination?: AudioNode
13
+ ) {
14
+ this.input = context.createGain();
15
+ this.output = context.createGain();
16
+ this.input.connect(this.output);
17
+ this.output.connect(destination ?? context.destination);
18
+ }
19
+
20
+ setVolume(value: number): void {
21
+ if (!Number.isFinite(value) || value < 0) {
22
+ throw new Error("Audio bus volume must be a non-negative finite number");
23
+ }
24
+ this.storedVolume = value;
25
+ if (!this.muted) {
26
+ this.output.gain.value = value;
27
+ }
28
+ }
29
+
30
+ mute(value = true): void {
31
+ this.muted = value;
32
+ this.output.gain.value = value ? 0 : this.storedVolume;
33
+ }
34
+
35
+ dispose(): void {
36
+ this.input.disconnect();
37
+ this.output.disconnect();
38
+ }
39
+ }
@@ -0,0 +1,26 @@
1
+ export interface AudioClipOptions {
2
+ readonly name?: string;
3
+ readonly buffer: AudioBuffer;
4
+ }
5
+
6
+ export class AudioClip {
7
+ readonly name?: string;
8
+ readonly buffer: AudioBuffer;
9
+
10
+ constructor(options: AudioClipOptions) {
11
+ this.name = options.name;
12
+ this.buffer = options.buffer;
13
+ }
14
+
15
+ get duration(): number {
16
+ return this.buffer.duration;
17
+ }
18
+
19
+ get channels(): number {
20
+ return this.buffer.numberOfChannels;
21
+ }
22
+
23
+ get sampleRate(): number {
24
+ return this.buffer.sampleRate;
25
+ }
26
+ }
@@ -0,0 +1,74 @@
1
+ export type AudioContextState = "locked" | "running" | "suspended" | "closed";
2
+
3
+ export interface AudioContextLike {
4
+ readonly state: AudioContextState | string;
5
+ readonly destination: AudioNode;
6
+ currentTime: number;
7
+ resume(): Promise<void>;
8
+ suspend(): Promise<void>;
9
+ close(): Promise<void>;
10
+ createGain(): GainNode;
11
+ createBufferSource(): AudioBufferSourceNode;
12
+ createPanner(): PannerNode;
13
+ createBiquadFilter(): BiquadFilterNode;
14
+ createConvolver(): ConvolverNode;
15
+ }
16
+
17
+ export interface AudioContextManagerOptions {
18
+ readonly context?: AudioContextLike;
19
+ readonly createContext?: () => AudioContextLike;
20
+ }
21
+
22
+ export class AudioContextManager {
23
+ private contextRef?: AudioContextLike;
24
+ private unlocked = false;
25
+
26
+ constructor(private readonly options: AudioContextManagerOptions = {}) {
27
+ this.contextRef = options.context;
28
+ }
29
+
30
+ get context(): AudioContextLike {
31
+ if (!this.contextRef) {
32
+ const createContext = this.options.createContext ?? (() => new AudioContext() as unknown as AudioContextLike);
33
+ this.contextRef = createContext();
34
+ }
35
+ return this.contextRef;
36
+ }
37
+
38
+ get state(): AudioContextState {
39
+ if (!this.contextRef) {
40
+ return "locked";
41
+ }
42
+ if (this.contextRef.state === "running") {
43
+ return "running";
44
+ }
45
+ if (this.contextRef.state === "closed") {
46
+ return "closed";
47
+ }
48
+ return this.unlocked ? "suspended" : "locked";
49
+ }
50
+
51
+ async unlock(): Promise<void> {
52
+ if (this.state === "closed") {
53
+ throw new Error("Cannot unlock a closed audio context");
54
+ }
55
+ await this.context.resume();
56
+ this.unlocked = true;
57
+ }
58
+
59
+ async suspend(): Promise<void> {
60
+ if (this.state !== "closed") {
61
+ await this.context.suspend();
62
+ }
63
+ }
64
+
65
+ async resume(): Promise<void> {
66
+ await this.unlock();
67
+ }
68
+
69
+ async dispose(): Promise<void> {
70
+ if (this.contextRef && this.contextRef.state !== "closed") {
71
+ await this.contextRef.close();
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,7 @@
1
+ export interface AudioEffect {
2
+ readonly input: AudioNode;
3
+ readonly output: AudioNode;
4
+ connect(destination: AudioNode): AudioNode;
5
+ disconnect(): void;
6
+ dispose(): void;
7
+ }