This repository provides a set of qualitative audio and visual diagnostic scripts for PsychoPy and Psychtoolbox (PTB) environments. The tests are designed to verify basic audio/visual functionality, device configuration, and channel separation on a variety of hardware setups. All tests are intended for quick, human-verifiable checks and are CI-friendly (always exit code 0).
Scripts in this repository allow you to:
- Run visual and audio sanity checks using PsychoPy (with keyboard input and color changes)
- Test single beep playback and device configuration using PTB
- Verify mixing and timing of overlapping tones
- Check stereo channel separation and crosstalk
test_psychopy.py— end-to-end PsychoPy check: real-time scheduling/privileges, fullscreen visual, keyboard input, and a beep per trial.test_ptb_single.py— plays a single beep through one PTB output stream; prints the full device list and selected device.test_ptb_mixed.py— plays one buffer with two overlapping tones (a D tone, with an A tone starting partway through) to check mixing and timing.test_ptb_stereo_mix.py— verifies stereo left/right separation: left-only, then right-only, then both tones simultaneously in their own channels.
- Python 3.8+
- PsychoPy (for visual/audio tests)
- psychtoolbox (for PTB tests)
- numpy
All scripts are standalone and can be run directly with Python 3 with PsychoPy and/or Psychtoolbox installed.
Run with the PsychoPy virtual environment's Python directly:
/opt/psychopy/PsychoPy-2026.1.3-Python3.10/.venv/bin/python3 test_psychopy.pyOr, using a PsychoPy distribution's launcher:
psychopy --direct test_psychopy.py
psychopy --direct test_ptb_single.pyEach script supports command-line arguments for device selection, sample rate, tone frequency, duration, and verbosity. Run a script with --help, or see the script header, for the full list.
Device selection is automatic and requires no configuration. The PTB test scripts (test_ptb_single.py, test_ptb_mixed.py, test_ptb_stereo_mix.py) and the patched PsychoPy SpeakerDevice select an output device by the same policy, in priority order:
- A device named
default— the ALSAdefaultPCM, which routes through PulseAudio/PipeWire and follows the system-selected sink. Present on most machines where PortAudio enumerates the ALSAdefaultPCM. - A device named
sysdefault. - The first analog hardware output, excluding HDMI/NVIDIA devices — the real onboard output on machines where
defaultis not enumerated by PortAudio (for example NVIDIA workstations where an HDMI audio card takes card 0). - The first device reporting output channels.
This policy is intentionally the same in the library and the test scripts, so the tests follow the same output as real experiments. It is designed to pick the correct output on machines with different audio stacks and card ordering without any per-host configuration — an identical image/container works across nodes.
For diagnostics, the test scripts accept explicit overrides:
--device-index N— force a specific numeric device index (from the printed device list).--device-name NAME— force a specific device name, e.g.--device-name default.
Note that device indices are not stable — they can change when hardware is added or removed — so the automatic policy (or --device-name) is more robust than pinning an index.
To list available devices without playing anything:
psychopy --direct test_ptb_stereo_mix.py --list-devicesThe ALSA default device routes through the sound server and follows the output chosen in the system sound settings, so it is preferred where available. Raw hardware devices (a USB dock, an HDMI port with nothing connected) can appear first in enumeration and bypass the sound server; the policy avoids them by preferring default/sysdefault and, when falling back to hardware, skipping HDMI/NVIDIA outputs in favour of the analog output. Where default is not enumerated (some PipeWire configurations, or machines where an NVIDIA HDMI card occupies card 0), the policy lands on the analog hardware output instead — which reaches the same physical speakers, though it does not follow the system-settings sink.
Some ALSA PCMs (notably default and sysdefault) advertise a large maximum channel count (e.g. 128). Opening a PTB stream at that width and then supplying stereo audio causes a FillBuffer channel-count mismatch. To avoid this, the scripts and the patched SpeakerDevice clamp the output to stereo (2 channels) by default, with no configuration needed.
If a node genuinely needs more output channels, set the PTB_MAX_OUT_CHANNELS environment variable to raise the cap:
export PTB_MAX_OUT_CHANNELS=8When unset, the effective cap is 2 (stereo). A value of 0 disables clamping and uses the device-reported channel count unchanged.
Number of columns of audio data matrix doesn't match number of output channels— the stream opened with more channels than the audio buffer has. This is handled by default (output is clamped to stereo); if you have raisedPTB_MAX_OUT_CHANNELS, lower it back to2.- Audio plays on the wrong output (e.g. an HDMI port or dock instead of the expected speaker) — the automatic policy normally avoids this by preferring
defaultand skipping HDMI/NVIDIA. Use--device-nameor--device-indexto force a specific device, and--list-devicesto see what PTB enumerates. - No sound at all — confirm the sound server is reachable (
pactl info) and inspect the script's device dump. On machines where PTB lists only rawhw:devices (nodefault), checkaplay -l/cat /proc/asound/cardsto see which card is the analog output; the policy targets the first analog, non-HDMI device.
MIT License (see LICENSE file).