完善客户端功能并同步差距文档

This commit is contained in:
shenlei
2026-09-03 18:40:01 +09:00
parent f93a172296
commit 13ccb8d02d
135 changed files with 21881 additions and 1259 deletions
+88
View File
@@ -0,0 +1,88 @@
# audio_miles_test —— MilesLib SoundManager 对齐回归。
# 验证 40250 的缩放、音量曲线和角色音效限频/距离规则。
extends SceneTree
const Audio = preload("res://audio.gd")
var _fail := 0
func _ck(condition: bool, message: String) -> void:
if not condition:
_fail += 1
printerr("FAIL: " + message)
func _init() -> void:
var audio := Audio.new()
get_root().add_child(audio)
_ck(is_equal_approx(Audio.SOUND_SCALE, 200.0), "sound scale is 200")
_ck(is_equal_approx(Audio.AMBIENCE_SOUND_SCALE, 1000.0), "ambience scale is 1000")
_ck(is_equal_approx(Audio.ratio_to_apply_volume(0.05), 0.05), "low ratio stays linear")
_ck(is_equal_approx(Audio.ratio_to_apply_volume(0.5), pow(10.0, -0.5)),
"ratio volume uses ClientVS22 logarithmic curve")
_ck(is_equal_approx(Audio.grade_to_apply_volume(5), 1.0), "grade 5 maps to full volume")
_ck(is_equal_approx(Audio.grade_to_apply_volume(0), 0.0), "grade 0 maps to silence")
audio.set_sound_scale(320.0)
audio.set_ambience_sound_scale(1200.0)
_ck(is_equal_approx(audio.get_sound_scale(), 320.0), "sound scale setter")
_ck(is_equal_approx(audio.get_ambience_sound_scale(), 1200.0), "ambience scale setter")
audio.set_listener(Vector3.ZERO, Vector3(0, 0, -1), Vector3.UP)
var assets := AssetRoot.path()
if DirAccess.dir_exists_absolute(assets):
audio.setup(assets)
var mss := assets.path_join("sound_m/sound/pc/warrior/general/run.mss")
if FileAccess.file_exists(mss):
var data: Array = audio.load_sound_information_piece(mss)
_ck(data.size() == 3, ".mss SoundDataCount and records parse")
_ck(is_equal_approx(float(data[0]["time"]), 0.759), ".mss preserves event time")
_ck(String(data[0]["sound"]) == "sound/common/walk_dirt_n.wav",
".mss preserves virtual sound path")
var instances: Array = audio.data_to_sound_instances(data)
_ck(int(instances[0]["frame"]) == 45 and int(instances[2]["frame"]) == 11,
".mss time converts to DWORD 60 FPS frames")
_ck(audio._find_sound(String(data[0]["sound"])) != "",
"virtual sound/ prefix resolves inside mounted sound root")
var motion := assets.path_join("PC/ymir work/pc/warrior/general/run.msa")
var motion_instances: Array = audio.load_mss_for_motion(motion)
_ck(motion_instances.size() == 3, "motion .msa resolves paired .mss")
var ambience := [{
"key": "waterfall-test",
"position": Vector3(20, 0, 0),
"range_cm": 3300,
"max_volume_area_percentage": 0.5,
"play_type": "LOOP",
"sounds": ["sound/ambience/warp_test.mp3"],
}]
audio.update_ambience_sources(ambience)
var ambience_state: Dictionary = audio._ambience_states.get("waterfall-test", {})
var ambience_id := int(ambience_state.get("id", -1))
_ck(ambience_id >= 0 and audio._active_3d.has(ambience_id),
"area ambience LOOP creates a Miles 3D instance")
if ambience_id >= 0 and audio._active_3d.has(ambience_id):
var ambience_player: AudioStreamPlayer3D = audio._active_3d[ambience_id]
_ck(abs(ambience_player.position.x - (20.0 * 100.0 / 1200.0)) < 0.001,
"ambience source uses cm -> ambience scale conversion")
audio.update_ambience_sources([])
_ck(not audio._ambience_states.has("waterfall-test") and not audio._active_3d.has(ambience_id),
"leaving / unloading area ambience stops its loop")
_ck(audio.can_play_character_sound("step.wav", Vector3(1, 0, 0), 10.0),
"near character sound is allowed")
_ck(not audio.can_play_character_sound("step.wav", Vector3(1, 0, 0), 10.2),
"same character sound is suppressed within 0.3 seconds")
_ck(audio.can_play_character_sound("step.wav", Vector3(1, 0, 0), 10.31),
"same character sound resumes after 0.3 seconds")
_ck(not audio.can_play_character_sound("far.wav", Vector3(51, 0, 0), 20.0),
"character sound beyond 5000cm is suppressed")
audio.set_sound_volume(0.0)
_ck(is_equal_approx(audio.master_sfx, 0.0), "sound volume setter accepts silence")
audio.stop_all_sound_3d()
audio.free()
if _fail == 0:
print("PASS: audio_miles_test (scale + volume curve + character sound guard)")
quit(0)
else:
printerr("%d check(s) failed" % _fail)
quit(1)