"""Gitea #51 A/B -- prove the stuck coolant sound before the fix, and gone after. Same session both ways; the only difference is BT_LOOP_LEGACY, which selects the OLD loop rule (`AL_LOOPING = sample != ForceStatic`) vs the new one (a LoopAtWill sample defers to the source's authored AudioRenderType). The measurement is the engine's own once-a-second playing-source dump (BT_AUDIO_DUMP): after all the flush releases, sit idle, then ask what is STILL playing with loop=1. A coolant source in that list is #51 reproduced. Kills only the PIDs it spawns. """ import ctypes import os import re import subprocess import sys import time KEYUP = 0x0002 VK_H = 0x48 VK_C = 0x43 user32 = ctypes.windll.user32 REPO = r"C:\git\bt411" def run(legacy): tag = "legacy" if legacy else "fixed" log = os.path.join(REPO, "scratchpad_loopab_%s.log" % tag) if os.path.exists(log): os.remove(log) env = dict(os.environ) env.update({ "BT_START_INSIDE": "1", "BT_KEY_NOFOCUS": "1", "BT_DEV_GAUGES": "1", "BT_AUDIO_DUMP": "1", "BT_FLUSH_LOG": "1", "BT_LOG": log, }) if legacy: env["BT_LOOP_LEGACY"] = "1" else: env.pop("BT_LOOP_LEGACY", None) p = subprocess.Popen( [os.path.join(REPO, "build", "Release", "btl4.exe"), "-egg", "LAST.EGG"], cwd=os.path.join(REPO, "content"), env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) print("[%s] pid %d" % (tag, p.pid)) try: deadline = time.time() + 240 while time.time() < deadline: if os.path.exists(log) and "first frame" in open(log, errors="replace").read(): break time.sleep(2) else: p.terminate() return tag, None time.sleep(6) # exercise the coolant plumbing: flush, valve, flush -- the pressure # inc/dec layers (LoopAtWill/Transient) are the suspect samples for _ in range(4): user32.keybd_event(VK_H, 0, 0, 0); time.sleep(0.5) user32.keybd_event(VK_H, 0, KEYUP, 0); time.sleep(0.6) user32.keybd_event(VK_C, 0, 0, 0); time.sleep(0.2) user32.keybd_event(VK_C, 0, KEYUP, 0); time.sleep(1.2) mark = len(open(log, errors="replace").read()) print("[%s] idling 25s" % tag) time.sleep(25) finally: p.terminate() time.sleep(1) t = open(log, errors="replace").read() idle = t[mark:] playing = re.findall(r"^\[playing\].*$", idle, re.M) stuck = {} for l in playing: m = re.search(r"src=(\d+) (\S+).*loop=(\d+)", l) if m and m.group(3) == "1": stuck[m.group(2)] = stuck.get(m.group(2), 0) + 1 return tag, stuck results = {} for legacy in (True, False): tag, stuck = run(legacy) results[tag] = stuck print("\n=============== A/B RESULT ===============") for tag in ("legacy", "fixed"): s = results.get(tag) if s is None: print("\n[%s] never reached the mission" % tag) continue coolant = {k: v for k, v in s.items() if "oolant" in k} print("\n[%s] still playing with loop=1 after all releases: %d distinct samples" % (tag, len(s))) for k, v in sorted(s.items(), key=lambda kv: -kv[1]): mark = " <-- COOLANT" if "oolant" in k else "" print(" %-30s seen %dx%s" % (k, v, mark)) print(" coolant sources stuck: %d" % len(coolant)) L = results.get("legacy") or {} F = results.get("fixed") or {} lc = len([k for k in L if "oolant" in k]) fc = len([k for k in F if "oolant" in k]) print("\nVERDICT: legacy coolant-stuck=%d fixed coolant-stuck=%d -> %s" % (lc, fc, "FIX CONFIRMED" if lc > fc else ("no coolant stick reproduced in either arm" if lc == 0 else "NOT fixed"))) sys.exit(0)