feat(rt+auth): batched input publish boi so 4 (het crackle) + auto-login loopback khong can mat khau
- fx_realtime: write_input gom FXRT_IN_SLOTS(4) frame vao _in_pending, flush ghi 1 lan + h.in_write += n (publish atomic -> bridge take=4 luon, het deficit) - plugins pump: flush_input_stale(0.004) dau vong lap -> input le khong ket - auth: _is_loopback(127.*/::1/localhost) -> get_current_user khong token = admin tu DB (must_change_password=False); POST /auth/local auto-login loopback, LAN 403 - ws fx-realtime: loopback khong token cho phep, remote thieu token -> close 4401 - UI: checkAuthStatus khong savedToken -> thu localLogin, thanh cong vao DAW, that bai -> modal login nhu cu; cache-buster v=202608212400
This commit is contained in:
+46
-13
@@ -113,6 +113,11 @@ class FxRealtimeSession:
|
||||
self.h.lat_slots = FXRT_LAT_SLOTS
|
||||
self._np = np.frombuffer(self.shm.buf, dtype=np.float32)
|
||||
self._lock = threading.Lock()
|
||||
# Input batching (fix crackle): gom FXRT_IN_SLOTS frame rồi publish 1 lần
|
||||
# (in_write += n atomic) → bridge luôn thấy bội số của FXRT_IN_SLOTS →
|
||||
# take=4 → batch xử lí. Không phụ thuộc client gửi burst hay lẻ.
|
||||
self._in_pending = []
|
||||
self._in_pending_t0 = None
|
||||
self.proc = None
|
||||
self._job_path = ""
|
||||
self._started_at = time.time()
|
||||
@@ -213,24 +218,52 @@ class FxRealtimeSession:
|
||||
|
||||
# ── audio I/O ───────────────────────────────────────────────────────────
|
||||
def write_input(self, interleaved):
|
||||
"""Ghi 1 block stereo float32 (2048 bytes) vào input ring. Ring đầy →
|
||||
drop block cũ nhất (giữ latency thấp)."""
|
||||
"""Gom FXRT_IN_SLOTS frame vào pending, đủ 4 → publish atomic vào ring
|
||||
(ghi data toàn bộ slot trước, sau đó in_write += n 1 lần). Ring đầy khi
|
||||
publish → drop batch cũ nhất (giữ latency thấp)."""
|
||||
arr = np.frombuffer(interleaved, dtype=np.float32)
|
||||
if arr.size != self.block_size * 2:
|
||||
return
|
||||
arr = arr.reshape(self.block_size, 2)
|
||||
with self._lock:
|
||||
h = self.h
|
||||
while True:
|
||||
if h.in_write - h.in_read < h.in_slots:
|
||||
slot = h.in_write & (h.in_slots - 1)
|
||||
bl = IN_L_OFF // 4 + slot * self.block_size
|
||||
br = IN_R_OFF // 4 + slot * self.block_size
|
||||
self._np[bl:bl + self.block_size] = arr[:, 0]
|
||||
self._np[br:br + self.block_size] = arr[:, 1]
|
||||
h.in_write += 1
|
||||
return
|
||||
h.in_read += 1 # full → drop oldest input
|
||||
if not self._in_pending:
|
||||
self._in_pending_t0 = time.time()
|
||||
self._in_pending.append((arr[:, 0].copy(), arr[:, 1].copy()))
|
||||
if len(self._in_pending) >= FXRT_IN_SLOTS:
|
||||
self._flush_input_locked()
|
||||
|
||||
def _flush_input_locked(self):
|
||||
"""Publish pending vào input ring. Ghi data trước, in_write += n sau →
|
||||
bridge đọc in_write 1 lần → thấy nguyên batch (take=4)."""
|
||||
if not self._in_pending:
|
||||
return
|
||||
h = self.h
|
||||
frames = self._in_pending
|
||||
self._in_pending = []
|
||||
self._in_pending_t0 = None
|
||||
avail = h.in_slots - (h.in_write - h.in_read)
|
||||
if avail <= 0:
|
||||
h.in_read += len(frames) # ring full → drop cả batch
|
||||
return
|
||||
n = min(len(frames), avail)
|
||||
drop = len(frames) - n
|
||||
if drop > 0:
|
||||
h.in_read += drop # drop frame cũ nhất
|
||||
for i in range(n):
|
||||
L, R = frames[i + drop]
|
||||
slot = (h.in_write + i) & (h.in_slots - 1)
|
||||
bl = IN_L_OFF // 4 + slot * self.block_size
|
||||
br = IN_R_OFF // 4 + slot * self.block_size
|
||||
self._np[bl:bl + self.block_size] = L
|
||||
self._np[br:br + self.block_size] = R
|
||||
h.in_write += n # publish atomic — bridge thấy đủ n block cùng lúc
|
||||
|
||||
def flush_input_stale(self, timeout=0.004):
|
||||
"""Flush pending nếu frame đầu chờ > timeout (client gửi lẻ/ngừng giữa
|
||||
burst) → không kẹt latency. Gọi từ _pump_output mỗi vòng."""
|
||||
with self._lock:
|
||||
if self._in_pending and self._in_pending_t0 is not None and time.time() - self._in_pending_t0 > timeout:
|
||||
self._flush_input_locked()
|
||||
|
||||
def read_output(self):
|
||||
"""Drain output ring → list bytes (mỗi block 2048 bytes interleaved)."""
|
||||
|
||||
Reference in New Issue
Block a user