PsychBench is built on Psychtoolbox, which is designed with timing precision as a priority. The same goes for PsychBench. Below is a technical summary of timing processes and precision. If you need more information, please contact us.
Note the timing precision of PsychBench is bounded by the timing precision of Psychtoolbox functions, which in turn depends on your operating system, hardware, and setup. For more information on this level, see for example psychtoolbox.org/requirements.
Some screen object properties set tradeoffs between visual timing precision and compatibility: doSyncTests, syncTestsParams, useCompositor. On systems where the high precision defaults cause problems in opening or closing the experiment window (especially on Mac, sometimes on Windows), you can switch to compatibility instead. Note Psychtoolbox recommends not running precise timing experiments on such systems. You can still develop and test precise timing experiments and/or run experiments that don’t need precise timing. Usually the easiest way to set these properties is with pb_prefs.
Internally PsychBench divides time during trials into short increments called frames. Frames are locked to refresh of the screen the experiment is running on: frame transition is always at screen refresh, and nominal frame rate = screen refresh rate. A common screen refresh / frame rate is 60 frames/sec (interval = 1/60 ≈ 17 msec). See screen object record properties refreshRate, refreshInterval.
Frames define the timing resolution for most events during trials. For example, PsychBench checks to start/end elements once per frame, dynamic displays change on screen up to once per frame at screen refresh, response handlers often poll for input at their devices once per frame, etc.
If a frame is too short for the processing that needs to run in it, it will extend to multiple screen refresh intervals. The other frames that would have run in those intervals are then “dropped”. This results in one iteration of all frame-based events where multiple were expected. For example, element start/end is delayed for one or more screen refreshes, animated element displays pause (but don’t disappear), etc. A record of actual frame rates and intervals achieved in each trial is available in trial object record properties frameRates, frameIntervals.
PsychBench generally recovers timing after dropped frames. e.g. if frames are dropped during an element running and before it ends, its end time later doesn’t change and its synchronization with other elements is not affected. (An exception is if the dropped frames occur at element start and so delay its start time, and it has an end condition like duration set. But this is because by definition end.duration goes off the element's actual start time.)
PsychBench checks to start/end elements once per frame, and element start/end aims to occur at the nearest frame transition. This is regardless of modality (visual, auditory, etc.). However, note visual elements in particular are further constrained physically to start or end at frame transition (screen refresh).
If you set the same start or end condition for different elements, they aim to start or end at the same nearest frame transition. This synchronizes them to the best precision Psychtoolbox allows.
There are various potential sources of deviation between expected element times and actual times you get during an experiment. There are also ways to avoid some of them if precise timing is important.
element.start.t = 2
element.end.t = 2.5
element.start.t = 2
element.end.duration = 0.5
→ Both these elements aim to start at 2 sec from trial start. Now suppose the time both actually start at is 2.017 sec (1 dropped frame at 60 frames/sec). Then the end.t condition (relative to trial start) would still aim to end the element at 2.500 sec, but the end.duration condition (relative to element start) would aim to end it at 2.517 sec. So for example you could use end.t to prioritize absolute end time of the element and end.duration to prioritize actual duration.
Element record properties startTime, endTime, duration record element times. Here are some common cases for how PsychBench gets these times:
Response, trigger, and other input times are measured by Psychtoolbox GetSecs, KbCheck, KbQueueCheck, and similar functions depending on the device and method. In the case of an element that checks for input once per frame (e.g. KbCheck), PsychBench measures input time as the average of time of check where the input was received and time of check in the previous frame, with a basic uncertainty of 1/2 the interval between checks (≈ 8 msec at 60 frames/sec with no dropped frames). In other cases where a background process is used to listen for input (e.g. KbQueueCheck), input time is measured directly by the process. See response handler record properties responseTime, responseLatency, d_responseTime, and element record properties triggerTime, d_triggerTime.