const OCCLUSION = {
    none: { lowpassHz: 20_000, volume: 1 },
    light: { lowpassHz: 8_000, volume: 0.9 },
    medium: { lowpassHz: 3_000, volume: 0.7 },
    heavy: { lowpassHz: 800, volume: 0.4 },
    complete: { lowpassHz: 200, volume: 0.1 }
};
export function sampleAudioEnvironmentFixture(options = {}) {
    const sourcePosition = options.sourcePosition ?? [0.85, 0.15, 0];
    const listenerPosition = options.listenerPosition ?? [0, 0, 3];
    const sourceVelocity = options.sourceVelocity ?? [-2.5, 0.2, 0];
    const listenerVelocity = options.listenerVelocity ?? [0.7, 0, 0];
    const obstacleCount = Math.max(0, Math.floor(options.obstacleCount ?? 2));
    const distance = vectorLength(sub(sourcePosition, listenerPosition));
    const direction = normalize(sub(listenerPosition, sourcePosition));
    const relativeVelocity = dot(sub(sourceVelocity, listenerVelocity), direction);
    const approaching = relativeVelocity > 0;
    const speedOfSound = 343;
    const pitchFactor = clamp(speedOfSound / Math.max(1, speedOfSound - relativeVelocity), 0.5, 2);
    const baseFrequencyHz = options.baseFrequencyHz ?? 440;
    const level = occlusionLevel(obstacleCount);
    const occlusion = OCCLUSION[level];
    const zoneRadius = Math.max(0.001, options.reverbZoneRadius ?? 8);
    const zoneDistance = Math.max(0, options.reverbZoneDistance ?? distance);
    const blend = clamp(1 - zoneDistance / zoneRadius, 0, 1);
    const fixture = {
        source: "origin-master-spatial-audio-environment-adapted",
        distance: round(distance),
        occlusion: {
            level,
            obstacleCount,
            lowpassHz: occlusion.lowpassHz,
            volume: occlusion.volume
        },
        doppler: {
            relativeVelocity: round(relativeVelocity),
            approaching,
            pitchFactor: round(pitchFactor),
            frequencyShiftHz: round(baseFrequencyHz * (pitchFactor - 1))
        },
        reverb: {
            zoneRadius: round(zoneRadius),
            zoneDistance: round(zoneDistance),
            blend: round(blend),
            wetLevel: round(0.55 * blend),
            dryLevel: round(0.85 * (1 - blend * 0.5))
        },
        hash: "",
        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."
    };
    return {
        ...fixture,
        hash: stableHash(`${fixture.distance}|${fixture.occlusion.level}|${fixture.occlusion.obstacleCount}|${fixture.doppler.pitchFactor}|${fixture.reverb.blend}`)
    };
}
function occlusionLevel(obstacleCount) {
    if (obstacleCount <= 0)
        return "none";
    if (obstacleCount === 1)
        return "light";
    if (obstacleCount === 2)
        return "medium";
    if (obstacleCount === 3)
        return "heavy";
    return "complete";
}
function sub(left, right) {
    return [left[0] - right[0], left[1] - right[1], left[2] - right[2]];
}
function dot(left, right) {
    return left[0] * right[0] + left[1] * right[1] + left[2] * right[2];
}
function normalize(value) {
    const length = vectorLength(value);
    return length > 0 ? [value[0] / length, value[1] / length, value[2] / length] : [0, 0, 0];
}
function vectorLength(value) {
    return Math.hypot(value[0], value[1], value[2]);
}
function clamp(value, min, max) {
    return Math.max(min, Math.min(max, Number.isFinite(value) ? value : min));
}
function round(value) {
    return Number(value.toFixed(4));
}
function stableHash(value) {
    let hash = 0x811c9dc5;
    for (let index = 0; index < value.length; index += 1) {
        hash ^= value.charCodeAt(index);
        hash = Math.imul(hash, 0x01000193);
    }
    return (hash >>> 0).toString(16).padStart(8, "0");
}
//# sourceMappingURL=SpatialAudioFixtures.js.map