Files
pyxis/tools/voice_test

pyxis voice-quality test harness (acoustic loopback)

Automated end-to-end test of the LXST voice pipeline using the Mac speaker next to the T-Deck mic. The Mac plays a known signal; the T-Deck captures it through the real pipeline (ES7210 mic → filters/AGC → Codec2 encode → call_send_audio_batch framing → call_on_packet parse → Codec2 decode) and streams the decoded PCM back over UDP. The harness re-aligns and scores the round-trip.

Physical setup

  • Mac built-in speaker within a few cm of the T-Deck mic, quiet room.
  • T-Deck on USB (serial control) and WiFi (UDP audio) — same LAN as the Mac.
  • Set the Mac output volume to a consistent moderate level.

Firmware contract (T:LOOPBACK test mode)

  • UDP multicast 239.0.99.99:9998, each datagram = [uint32 LE byte-offset][int16 LE mono @ 8 kHz PCM], ≤1284 B.
  • Serial hooks: T:CALL_PROFILE 0x10|0x20|0x30 (ULBW/VLBW/LBW), T:LOOPBACK on|off.

Run

cd tools/voice_test
.venv/bin/python run_voice_test.py --port /dev/cu.usbmodem101 --profiles ULBW,VLBW,LBW
# options: --ref my.wav   --text "..."   --output "Mac mini Speakers"   --tail 1.2

Outputs out/reference.wav + out/captured_<profile>.wav (listen to confirm) and a summary table.

Metrics

  • STOI (01): objective intelligibility (≥0.55 ≈ intelligible). Primary score.
  • corr: time-aligned, gain-matched waveform correlation of the speech region.
  • segSNR (dB): segmental SNR after alignment/gain-match.
  • band: speech-band (3003400 Hz) energy survival vs reference.
  • hf: high-band (23.4 kHz) survival — Codec2 low profiles roll off the top.
  • pkts / dropped: UDP delivery health.

Lower-bitrate profiles (700C) score lower by design; compare profiles and before/after firmware changes. The venv was created with uv venv --python 3.12 + numpy scipy soundfile sounddevice pyserial pystoi.

Sideband/LXST end-to-end regression

sideband_e2e.py uses the Mac's real RNS/LXST/Sideband Python stack and the T-Deck serial hooks to verify:

  • Pyxis calls Sideband and exchanges synthetic Codec2 audio in both directions.
  • Sideband calls Pyxis and exchanges synthetic Codec2 audio in both directions.
  • Pyxis still accepts another incoming call after both calls and hangups.
  • Every Pyxis decode succeeds and produces non-zero PCM.

Build the test firmware with the Mac TCP server baked in, then upload it:

export PYXIS_TEST_TCP_HOST=10.0.0.145 PYXIS_TEST_TCP_PORT=4242
/opt/homebrew/bin/pio run -e tdeck -t upload --upload-port /dev/cu.usbmodem101

Run from the Mac with its Reticulum venv (defaults to the local TCP server on 127.0.0.1:4242):

~/.reticulum-host/venv/bin/python tools/voice_test/sideband_e2e.py

Optional overrides: PYXIS_SERIAL_PORT, PYXIS_RNS_HOST, PYXIS_RNS_PORT, and PYXIS_CALL_SECONDS. Each run uses a fresh Sideband identity and isolated RNS storage so stale cached paths cannot false-pass setup. On Apple Silicon the harness re-executes itself with /opt/homebrew/lib on DYLD_LIBRARY_PATH, allowing LXST/PyOgg to load Homebrew libopus for incoming calls.