frameRemains = 1000 + 1.0- win.monitorFramePeriod * 0.75

The PsychoPy in-house generated code has a section that usually looks something like this:

if t >= 0.0 and opening_text.status == NOT_STARTED:
    # keep track of start time/frame for later
   opening_text.tStart = t
   opening_text.frameNStart = frameN  # exact frame index
   opening_text.setAutoDraw(True)
frameRemains = 0.0 + 1.0- win.monitorFramePeriod * 0.75  # most of one frame period left
if opening_text.status == STARTED and t >= frameRemains:
   opening_text.setAutoDraw(False)

In some dodgy Frankenstein-ing of this, I’ve ended up using the following bit of code:

frameRemains = 1000 + 1.0- win.monitorFramePeriod * 0.75  
if audio_feedback.status == STARTED and t >= frameRemains:
   audio_feedback.stop()  
if audio_feedback.status == FINISHED and correct_text.status == FINISHED or incorrect_text.status == FINISHED:
   continueRoutine = False 

This was a budget solution to a problem: PsychoPy was always cutting audio_feedback short when it played. If the participant took a short time to respond then the whole of audio_feedback would play. However if they took a long time then it would often cut short, and sometimes not even play at all.

I found that replacing 0.0 with 1000, resulting in a much larger frameRemains variable, fixed this issue on a surface level - audio_feedback is no longer cut short. However I don’t know the possible further implications of this, and it’s obviously not great to Frankenstein code when you don’t know what it’s supposed to be doing…

What are the implications of what I’ve done here? Is there a better way to fix the initial problem?

It does seem very dodgy to make a variable contain something other than what it is supposed to represent. That could break things if frameRemains is used in subsequent code, and makes things very hard to maintain (you have to remember in the future that sometimes this variable is meaningful and sometimes it contains a junk value).

The solution is easy: you don’t actually have to stop an audio stimulus playing. Builder code just does that because that is the way its interface is set up with the timeline view. But you could simply delete these lines:

if audio_feedback.status == STARTED and t >= frameRemains:
   audio_feedback.stop()  

That way, the sound will just naturally stop playing all by itself, when it has completed. Just beware that this may extend into a following trial, for example, because you aren’t controlling its end point any more.

1 Like

Brilliant, thank you - that worked!