Add audio capture timing metrics to target pipeline

Instrument AudioCaptureStream with read/FFT timing and
AudioColorStripStream with render timing. Display audio-specific
timing segments (read/fft/render/send) in the target card
breakdown bar when an audio source is active.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 20:41:29 +03:00
parent a39dc1b06a
commit 34d9495eb3
6 changed files with 86 additions and 7 deletions

View File

@@ -123,6 +123,9 @@ class AudioCaptureStream:
self._smooth_spectrum_left = np.zeros(NUM_BANDS, dtype=np.float32)
self._smooth_spectrum_right = np.zeros(NUM_BANDS, dtype=np.float32)
# Per-iteration timing (written by capture thread, read by consumers)
self._last_timing: dict = {}
def start(self) -> None:
if self._running:
return
@@ -150,6 +153,10 @@ class AudioCaptureStream:
with self._lock:
return self._latest
def get_last_timing(self) -> dict:
"""Return per-iteration timing from the capture loop (ms)."""
return dict(self._last_timing)
def _capture_loop(self) -> None:
try:
import pyaudiowpatch as pyaudio
@@ -211,6 +218,7 @@ class AudioCaptureStream:
spectrum_buf_right = np.zeros(NUM_BANDS, dtype=np.float32)
while self._running:
t_read_start = time.perf_counter()
try:
raw_data = stream.read(self._chunk_size, exception_on_overflow=False)
data = np.frombuffer(raw_data, dtype=np.float32)
@@ -218,6 +226,7 @@ class AudioCaptureStream:
logger.warning(f"Audio read error: {e}")
time.sleep(0.05)
continue
t_read_end = time.perf_counter()
# Split channels and mix to mono
if channels > 1:
@@ -275,6 +284,12 @@ class AudioCaptureStream:
beat = True
beat_intensity = min(1.0, (ratio - 1.0) / 2.0)
t_fft_end = time.perf_counter()
self._last_timing = {
"read_ms": (t_read_end - t_read_start) * 1000,
"fft_ms": (t_fft_end - t_read_end) * 1000,
}
analysis = AudioAnalysis(
timestamp=time.perf_counter(),
rms=rms,