psychopy.org | Reference | Downloads | Github

How to play and repeat stimuli after manual click?

Hi,

in my current code there is a sequence of sound stimuli (2 in this example) which are randomized.
Each stimulus has to be rated from 1 to 5, and after each rating the next stimulus starts playing automatically and is played just for one time.

What I would like to implement now is:
- a PLAY button which allows to start playing the sound ony when the participant likes, so no more automatic starting;
- the play button can be pressed as many times as one likes, so many repetitions are allowed;

  • as now, after evaluation on the rating scale + confirmation by clicking inside the white box below the ratingscale, the experiment continues with the following stimulus;
  • as now, the order of presentation of the stimuli is randomized.

I attach the code.

Many thanks,
Erica

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
This experiment was created using PsychoPy2 Experiment Builder (v1.81.00), Ven 13 Lug 14:04:33 2018
If you publish work using this script please cite the relevant PsychoPy publications
  Peirce, JW (2007) PsychoPy - Psychophysics software in Python. Journal of Neuroscience Methods, 162(1-2), 8-13.
  Peirce, JW (2009) Generating stimuli for neuroscience using PsychoPy. Frontiers in Neuroinformatics, 2:10. doi: 10.3389/neuro.11.010.2008
"""

from __future__ import division  # so that 1/3=0.333 instead of 1/3=0
from psychopy import visual, core, data, event, logging, sound, gui
from psychopy.constants import *  # things like STARTED, FINISHED
import numpy as np  # whole numpy lib is available, prepend 'np.'
from numpy import sin, cos, tan, log, log10, pi, average, sqrt, std, deg2rad, rad2deg, linspace, asarray
from numpy.random import random, randint, normal, shuffle
import os  # handy system and path functions

# Ensure that relative paths start from the same directory as this script
_thisDir = os.path.dirname(os.path.abspath(__file__))
os.chdir(_thisDir)

# Store info about the experiment session
expName = 'Output-Trial'  # from the Builder filename that created this script
expInfo = {u'session': u'001', u'participant': u''}
dlg = gui.DlgFromDict(dictionary=expInfo, title=expName)
if dlg.OK == False: core.quit()  # user pressed cancel
expInfo['date'] = data.getDateStr()  # add a simple timestamp
expInfo['expName'] = expName

# Data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc
filename = _thisDir + os.sep + 'data/%s_%s_%s' %(expInfo['participant'], expName, expInfo['date'])

# An ExperimentHandler isn't essential but helps with data saving
thisExp = data.ExperimentHandler(name=expName, version='',
    extraInfo=expInfo, runtimeInfo=None,
    originPath=None,
    savePickle=True, saveWideText=True,
    dataFileName=filename)
#save a log file for detail verbose info
logFile = logging.LogFile(filename+'.log', level=logging.EXP)
logging.console.setLevel(logging.WARNING)  # this outputs to the screen, not a file

endExpNow = False  # flag for 'escape' or other condition => quit the exp

# Start Code - component code to be run before the window creation

# Setup the Window
win = visual.Window(size=[1680, 1050], fullscr=False, screen=0, allowGUI=True, allowStencil=False,
    monitor='testMonitor', color=[-1.000,-1.000,-1.000], colorSpace='rgb',
    blendMode='avg', useFBO=True,
    )
# store frame rate of monitor if we can measure it successfully
expInfo['frameRate']=win.getActualFrameRate()
if expInfo['frameRate']!=None:
    frameDur = 1.0/round(expInfo['frameRate'])
else:
    frameDur = 1.0/60.0 # couldn't get a reliable measure so guess

# Initialize components for Routine "Instruction_1"
Instruction_1Clock = core.Clock()
text = visual.TextStim(win=win, ori=0, name='text',
    text=u"Le projet de recherche auquel vous participez porte sur la perception du TIMBRE (pris dans un sens large : couleur du son, texture, toute notion \xe0 l\u2019exception de la hauteur de la note).\n. \n\nVous entendrez 37 paires de sons. Pour chaque paire, vous serez appel\xe9s \xe0 r\xe9aliser une t\xe2che. \n\nIl n'y a pas de bonne ou de mauvaise r\xe9ponse, puisqu'il s'agit d'indiquer quelle est votre perception. \nLa dur\xe9e moyenne de ce test est de 30 minutes. \n\nVous aurez deux essais pour vous familiariser avec la t\xe2che demand\xe9e, avant que ne commence l\u2019exp\xe9rience.\n\n\nVeuillez passer \xe0 la diapositive suivante en appuyant sur la barre d'espace.",    font='Arial',
    pos=[0, 0], height=0.07, wrapWidth=None,
    color='white', colorSpace='rgb', opacity=1,
    depth=0.0)

# Initialize components for Routine "Instruction_2"
Instruction_2Clock = core.Clock()
text_2 = visual.TextStim(win=win, ori=0, name='text_2',
    text=u"Au cours de cette exp\xe9rience, vous entendrez des s\xe9quences de paires de sons.\n\n\nVous serez appel\xe9s \xe0 \xe9valuer, sur une \xe9chelle de 1 \xe0 5, le degr\xe9 de SIMILARIT\xc9 entre les sons de chaque paire.\n\nVous pouvez \xe9couter chaque paire de stimuli deux fois de suite, s\xe9par\xe9es par un court intervalle de temps.\n\nVeuillez indiquer votre choix (une seule \xe9coute de la paire ou deux \xe9coutes successives de la paire) apr\xe8s l\u2019\xe9coute de la paire de stimuli.\n\n\nVeuillez passer \xe0 la diapositive suivante en appuyant sur la barre d'espace lorsque vous serez pr\xeat.",    font='Arial',
    pos=[0, 0], height=0.07, wrapWidth=None,
    color='white', colorSpace='rgb', opacity=1,
    depth=0.0)

# Initialize components for Routine "Instruction_3"
Instruction_3Clock = core.Clock()
text_3 = visual.TextStim(win=win, ori=0, name='text_3',
    text="Maintenant, vous allez entendre le premier extrait.\n\nAppuyez sur la barre d'espace pour continuer. \n\n",    font='Arial',
    pos=[0, 0], height=0.07, wrapWidth=None,
    color='white', colorSpace='rgb', opacity=1,
    depth=0.0)

# Initialize components for Routine "trial1_2"
trial1_2Clock = core.Clock()
text_7 = visual.TextStim(win=win, ori=0, name='text_7',
    text=u"Au commencement du second extrait de chaque paire, veuillez \xe9valuer le degr\xe9 de SIMILARIT\xc9 ENTRE LES DEUX SONS, de 1 \xe0 5, en cliquant sur l'un des points de l'\xe9chelle. \n\nVous pouvez changer votre \xe9valuation \xe0 votre guise. \nPour soumettre votre choix de mani\xe8re d\xe9finitive, cliquez dans le rectangle au bas de la page.",    font='Arial',
    pos=[0, 0.2], height=0.07, wrapWidth=None,
    color='white', colorSpace='rgb', opacity=1,
    depth=0.0)
text_8 = visual.TextStim(win=win, ori=0, name='text_8',
    text='default text',    font='Arial',
    pos=[0.8, 0.6], height=0.2, wrapWidth=None,
    color='yellow', colorSpace='rgb', opacity=1,
    depth=-1.0)
text_9 = visual.TextStim(win=win, ori=0, name='text_9',
    text='default text',    font='Arial',
    pos=[0.8, 0.75], height=0.05, wrapWidth=None,
    color='yellow', colorSpace='rgb', opacity=1,
    depth=-2.0)
text_10 = visual.TextStim(win=win, ori=0, name='text_10',
    text='default text',    font='Arial',
    pos=[0.73, 0.6], height=0.2, wrapWidth=None,
    color='yellow', colorSpace='rgb', opacity=1,
    depth=-3.0)
similarity = visual.RatingScale(win=win, name='similarity', marker='triangle',
markerColor='red',
size=0.7,
pos=[0, -0.6], 
low=1, 
high=5,
labels=[''],
scale=u'1 = tr\xe8s diff\xe9rent                   5 = tr\xe8s semblable',
disappear=True)
sound_6 = sound.Sound('A')
sound_6.setVolume(1)


# Initialize components for Routine "End"
EndClock = core.Clock()
text_12 = visual.TextStim(win=win, ori=0, name='text_12',
    text=u'F\xe9licitations, vous avez bien effectu\xe9 la t\xe2che demand\xe9e. \n\nVeuillez appuyer sur la barre d\u2019espace lorsque vous aurez termin\xe9.',    font='Arial',
    pos=[0, 0], height=0.07, wrapWidth=None,
    color='white', colorSpace='rgb', opacity=1,
    depth=0.0)

# Create some handy timers
globalClock = core.Clock()  # to track the time since experiment started
routineTimer = core.CountdownTimer()  # to track time remaining of each (non-slip) routine 

#------Prepare to start Routine "Instruction_1"-------
t = 0
Instruction_1Clock.reset()  # clock 
frameN = -1
# update component parameters for each repeat
key_resp_2 = event.BuilderKeyResponse()  # create an object of type KeyResponse
key_resp_2.status = NOT_STARTED
# keep track of which components have finished
Instruction_1Components = []
Instruction_1Components.append(text)
Instruction_1Components.append(key_resp_2)
for thisComponent in Instruction_1Components:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

#-------Start Routine "Instruction_1"-------
continueRoutine = True
while continueRoutine:
    # get current time
    t = Instruction_1Clock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *text* updates
    if t >= 0.0 and text.status == NOT_STARTED:
        # keep track of start time/frame for later
        text.tStart = t  # underestimates by a little under one frame
        text.frameNStart = frameN  # exact frame index
        text.setAutoDraw(True)
    
    # *key_resp_2* updates
    if t >= 0.0 and key_resp_2.status == NOT_STARTED:
        # keep track of start time/frame for later
        key_resp_2.tStart = t  # underestimates by a little under one frame
        key_resp_2.frameNStart = frameN  # exact frame index
        key_resp_2.status = STARTED
        # keyboard checking is just starting
        event.clearEvents(eventType='keyboard')
    if key_resp_2.status == STARTED:
        theseKeys = event.getKeys(keyList=['space'])
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            # a response ends the routine
            continueRoutine = False
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        routineTimer.reset()  # if we abort early the non-slip timer needs reset
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in Instruction_1Components:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the Esc key)
    if endExpNow or event.getKeys(keyList=["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()
    else:  # this Routine was not non-slip safe so reset non-slip timer
        routineTimer.reset()

#-------Ending Routine "Instruction_1"-------
for thisComponent in Instruction_1Components:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)

#------Prepare to start Routine "Instruction_2"-------
t = 0
Instruction_2Clock.reset()  # clock 
frameN = -1
# update component parameters for each repeat
key_resp_3 = event.BuilderKeyResponse()  # create an object of type KeyResponse
key_resp_3.status = NOT_STARTED
# keep track of which components have finished
Instruction_2Components = []
Instruction_2Components.append(text_2)
Instruction_2Components.append(key_resp_3)
for thisComponent in Instruction_2Components:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

#-------Start Routine "Instruction_2"-------
continueRoutine = True
while continueRoutine:
    # get current time
    t = Instruction_2Clock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *text_2* updates
    if t >= 0.0 and text_2.status == NOT_STARTED:
        # keep track of start time/frame for later
        text_2.tStart = t  # underestimates by a little under one frame
        text_2.frameNStart = frameN  # exact frame index
        text_2.setAutoDraw(True)
    
    # *key_resp_3* updates
    if t >= 0.0 and key_resp_3.status == NOT_STARTED:
        # keep track of start time/frame for later
        key_resp_3.tStart = t  # underestimates by a little under one frame
        key_resp_3.frameNStart = frameN  # exact frame index
        key_resp_3.status = STARTED
        # keyboard checking is just starting
        event.clearEvents(eventType='keyboard')
    if key_resp_3.status == STARTED:
        theseKeys = event.getKeys(keyList=['space'])
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            # a response ends the routine
            continueRoutine = False
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        routineTimer.reset()  # if we abort early the non-slip timer needs reset
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in Instruction_2Components:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the Esc key)
    if endExpNow or event.getKeys(keyList=["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()
    else:  # this Routine was not non-slip safe so reset non-slip timer
        routineTimer.reset()

#-------Ending Routine "Instruction_2"-------
for thisComponent in Instruction_2Components:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)

#------Prepare to start Routine "Instruction_3"-------
t = 0
Instruction_3Clock.reset()  # clock 
frameN = -1
# update component parameters for each repeat
key_resp_4 = event.BuilderKeyResponse()  # create an object of type KeyResponse
key_resp_4.status = NOT_STARTED
# keep track of which components have finished
Instruction_3Components = []
Instruction_3Components.append(text_3)
Instruction_3Components.append(key_resp_4)
for thisComponent in Instruction_3Components:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

#-------Start Routine "Instruction_3"-------
continueRoutine = True
while continueRoutine:
    # get current time
    t = Instruction_3Clock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *text_3* updates
    if t >= 0.0 and text_3.status == NOT_STARTED:
        # keep track of start time/frame for later
        text_3.tStart = t  # underestimates by a little under one frame
        text_3.frameNStart = frameN  # exact frame index
        text_3.setAutoDraw(True)
    
    # *key_resp_4* updates
    if t >= 0.0 and key_resp_4.status == NOT_STARTED:
        # keep track of start time/frame for later
        key_resp_4.tStart = t  # underestimates by a little under one frame
        key_resp_4.frameNStart = frameN  # exact frame index
        key_resp_4.status = STARTED
        # keyboard checking is just starting
        event.clearEvents(eventType='keyboard')
    if key_resp_4.status == STARTED:
        theseKeys = event.getKeys(keyList=['space'])
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            # a response ends the routine
            continueRoutine = False
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        routineTimer.reset()  # if we abort early the non-slip timer needs reset
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in Instruction_3Components:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the Esc key)
    if endExpNow or event.getKeys(keyList=["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()
    else:  # this Routine was not non-slip safe so reset non-slip timer
        routineTimer.reset()

#-------Ending Routine "Instruction_3"-------
for thisComponent in Instruction_3Components:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)

# set up handler to look after randomisation of conditions etc
trials = data.TrialHandler(nReps=1, method='random', 
    extraInfo=expInfo, originPath=None,
    trialList=data.importConditions('datasound.xlsx'),
    seed=None, name='trials')
thisExp.addLoop(trials)  # add the loop to the experiment
thisTrial = trials.trialList[0]  # so we can initialise stimuli with some values
# abbreviate parameter names if possible (e.g. rgb=thisTrial.rgb)
if thisTrial != None:
    for paramName in thisTrial.keys():
        exec(paramName + '= thisTrial.' + paramName)

for thisTrial in trials:
    currentLoop = trials
    # abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
    if thisTrial != None:
        for paramName in thisTrial.keys():
            exec(paramName + '= thisTrial.' + paramName)
    
    #------Prepare to start Routine "trial1_2"-------
    t = 0
    trial1_2Clock.reset()  # clock 
    frameN = -1
    # update component parameters for each repeat
    text_8.setText(trials.nRemaining+1)
    text_9.setText(u'compte \xe0 rebours')
    text_10.setText('-')
    similarity.reset()
    sound_6.setSound(Sound)
    scaleList2 = [similarity]
    # keep track of which components have finished
    trial1_2Components = []
    trial1_2Components.append(text_7)
    trial1_2Components.append(text_8)
    trial1_2Components.append(text_9)
    trial1_2Components.append(text_10)
    trial1_2Components.append(similarity)
    trial1_2Components.append(sound_6)
    for thisComponent in trial1_2Components:
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    
    #-------Start Routine "trial1_2"-------
    continueRoutine = True
    while continueRoutine:
        # get current time
        t = trial1_2Clock.getTime()
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *text_7* updates
        if t >= 0.0 and text_7.status == NOT_STARTED:
            # keep track of start time/frame for later
            text_7.tStart = t  # underestimates by a little under one frame
            text_7.frameNStart = frameN  # exact frame index
            text_7.setAutoDraw(True)
        
        # *text_8* updates
        if t >= 0.0 and text_8.status == NOT_STARTED:
            # keep track of start time/frame for later
            text_8.tStart = t  # underestimates by a little under one frame
            text_8.frameNStart = frameN  # exact frame index
            text_8.setAutoDraw(True)
        
        # *text_9* updates
        if t >= 0.0 and text_9.status == NOT_STARTED:
            # keep track of start time/frame for later
            text_9.tStart = t  # underestimates by a little under one frame
            text_9.frameNStart = frameN  # exact frame index
            text_9.setAutoDraw(True)
        
        # *text_10* updates
        if t >= 0.0 and text_10.status == NOT_STARTED:
            # keep track of start time/frame for later
            text_10.tStart = t  # underestimates by a little under one frame
            text_10.frameNStart = frameN  # exact frame index
            text_10.setAutoDraw(True)
        # *similarity* updates
        if t > 0.0:
            similarity.draw()
            if similarity.noResponse == False:
                similarity.response = similarity.getRating()
        # start/stop sound_6
        if t >= 0.0 and sound_6.status == NOT_STARTED:
            # keep track of start time/frame for later
            sound_6.tStart = t  # underestimates by a little under one frame
            sound_6.frameNStart = frameN  # exact frame index
            sound_6.play()  # start the sound (it finishes automatically)
        count = 0 
        for s in scaleList2: 
            if not s.noResponse: 
                count += 1 
        if count == 1: 
            continueRoutine = False
        
        # check if all components have finished
        if not continueRoutine:  # a component has requested a forced-end of Routine
            routineTimer.reset()  # if we abort early the non-slip timer needs reset
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in trial1_2Components:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # check for quit (the Esc key)
        if endExpNow or event.getKeys(keyList=["escape"]):
            core.quit()
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
        else:  # this Routine was not non-slip safe so reset non-slip timer
            routineTimer.reset()
    
    #-------Ending Routine "trial1_2"-------
    for thisComponent in trial1_2Components:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    # store data for trials (TrialHandler)
    trials.addData('similarity.response', similarity.getRating())
    sound_6.stop()
    
    
    thisExp.nextEntry()
    
# completed 1 repeats of 'trials'

# get names of stimulus parameters
if trials.trialList in ([], [None], None):  params = []
else:  params = trials.trialList[0].keys()
# save data for this loop
trials.saveAsExcel(filename + '.xlsx', sheetName='trials',
    stimOut=params,
    dataOut=['n','all_mean','all_std', 'all_raw'])

#------Prepare to start Routine "End"-------
t = 0
EndClock.reset()  # clock 
frameN = -1
# update component parameters for each repeat
key_resp_10 = event.BuilderKeyResponse()  # create an object of type KeyResponse
key_resp_10.status = NOT_STARTED
# keep track of which components have finished
EndComponents = []
EndComponents.append(text_12)
EndComponents.append(key_resp_10)
for thisComponent in EndComponents:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

#-------Start Routine "End"-------
continueRoutine = True
while continueRoutine:
    # get current time
    t = EndClock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *text_12* updates
    if t >= 0.0 and text_12.status == NOT_STARTED:
        # keep track of start time/frame for later
        text_12.tStart = t  # underestimates by a little under one frame
        text_12.frameNStart = frameN  # exact frame index
        text_12.setAutoDraw(True)
    
    # *key_resp_10* updates
    if t >= 0.0 and key_resp_10.status == NOT_STARTED:
        # keep track of start time/frame for later
        key_resp_10.tStart = t  # underestimates by a little under one frame
        key_resp_10.frameNStart = frameN  # exact frame index
        key_resp_10.status = STARTED
        # keyboard checking is just starting
        event.clearEvents(eventType='keyboard')
    if key_resp_10.status == STARTED:
        theseKeys = event.getKeys(keyList=['space'])
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            # a response ends the routine
            continueRoutine = False
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        routineTimer.reset()  # if we abort early the non-slip timer needs reset
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in EndComponents:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the Esc key)
    if endExpNow or event.getKeys(keyList=["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()
    else:  # this Routine was not non-slip safe so reset non-slip timer
        routineTimer.reset()

#-------Ending Routine "End"-------
for thisComponent in EndComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)

win.close()
core.quit()

Hi @ericabisesi, yes this is possible and in this case I have used the right mouse button to replay the sound. You could add a code component in the Builder view. In the Start Routine tab, add:

 def playSound():
    beep = sound.Sound('A', secs=.3)  # You will probably need to add your sound variable e.g. 'Sound'
    beep.setVolume(1)
    beep.play()
    core.wait(.3)

In the Every Frame tab, add the following which checks whether or not the right mouse button was clicked:

if mouse.getPressed()[2] != 0:
    playSound()  # Call your playSound function defined at the beginning of the routine

Hallo David,

thanks for having considered my request.

  1. The error is:

if mouse.getPressed()[2] != 0:
NameError: name ‘mouse’ is not defined

How can I define the “mouse”?

  1. There is a sentence (by you) I don’t understand:
 You will probably need to add your sound variable e.g. 'Sound'

What should I do there?

  1. I attach 3 screenshots to check for compatibility with previous statements in the routines after adding the code.

Thanks, see you soon.

Erica

Apologies, I had interpretted “push a button” as a mouse button and has assumed you were using a mouse. You could swap that code with something that checks for a key press instead. See the Keyboard API here.

For ‘Sound’, you have a variable in your code called ‘Sound’, which I believe will be a column in your datafile, which should be a list of your sound files. So, rather than setting sound to an ‘A’ note in the function called playSound, you will want to set your sound to the sound variable holding your sound file name that is to be played.

Yes your code looks fine, although you will want to replace the conditional that relies on a mouse click to something else, as above.

I don’t understand…

I connected a mouse and this does not fix the problem, can you say me why? Just to understand…

Then I looked at other options as you suggested… Anyway I am wondering why it wouldn’t be easier to define the ‘mouse’.

Maybe I explained badly. With “push a button” I meant that an interactive option will appear on the screen with a PLAY indicator (like the little arrow on youtube).

This would be optiomal.

But also the spacebar can work, or any other key.

In this second case I kindly ask to tell me ho w to code… I see also the picture of a keyboard in the Components Menu, maybe something from there? But I don’t understand how to link to the rest.

Erica

Ok, well if you add a mouse component to the relevant routine in Builder, and call it ‘mouse’ (which is the default name) - it should work. Although, you will need to make sure that the mouse is not set up to end the routine on any click, else your trial will end without the option of repeats.

If you want to use a shape on screen, you need to make sure that you are using a version of psychopy that supports the use of the isPressedIn function - see here. You would then use this function like this, in the ‘Each Frame’ tab of your code component:

if mouse.isPressedIn(<Name of your shape>, buttons=0):
    playSound()

Alternatively, use a keyboard and add the following to the coder in the ‘Each Frame’:

if event.getKeys(keyList=["space"]):
    playSound()

This will allow you to use the spacebar to repeat trials :slight_smile:

Hi @dvbridges,
Thanks for your suggestion. This was really helpful. While I was able to make it work in the local PsychoPy experiment, this does not work online. I think the problem is due to the function you created, playsound, is not defined in Javascript. I was wondering if you could help translating the python code below into Javascript.

def playSound():
    beep = sound.Sound('A', secs=.3)  # You will probably need to add your sound variable e.g. 'Sound'
    beep.setVolume(1)
    beep.play()
    core.wait(.3)

Thank you!

Hi @HungShao, you could try:

playSound = function() {
  beep = new Sound({
    win: psychoJS.window,
    value: "A",
    secs: .3,
  });
  beep.setVolume(1);
  beep.play()
}

Hi @dvbridges.

thank you! I put the code into the experiment and change “A” to the variable, sounds. However, this error came up when I right click the mouse.

This is the code I have
Begin Routine

modify = false;
text.text = "";

playSound = function() {
  beep = new Sound({
    win: psychoJS.window,
    value: sounds,
    secs: .3,
  });
  beep.setVolume(1);
  beep.play()
}

Each frame

let theseKeys = psychoJS.eventManager.getKeys();
if (theseKeys.length > 0) {  // at least one key was pressed
  textAdd = theseKeys[theseKeys.length-1]; 
  }


if (textAdd === 'return') {
    textAdd = '';  // Add nothing
    continueRoutine = false;  // End routine (if that is what you want)
} else if (textAdd === 'space') {
    textAdd = ' ';  // Add a space
} else if (textAdd === 'backspace') {
    text.text = text.text.slice(0, -1);
    textAdd = undefined;
} else if (['lshift', 'rshift'].includes(textAdd)) {
    modify = true;
} else if (textAdd !== undefined) {
    if (modify) {
        text.text = text.text + textAdd.toUpperCase();
        modify = false;
    } else {
        text.text = text.text + textAdd
    }
    textAdd = undefined;
}

if ((mouse.getPressed()[2] !== 0)) {
    playSound();
}

I am guessing this error is due to the found file can’t be found? But i am not so sure, do you know what the errors might be here and any solutions?

Thanks again! Really appreciate your help.

Hi @dvbridges,

I tried to modify your code a little bit (not sure if it is the right move) and I was able to get the sound to play after right-clicking the mouse. However, the sound is very distorted and it also affect the quality of any subsequent sounds. Is Each Frame not the right place to add the code? Here is the modification as well as the URL of the experiment

Begin Routine

modify = false;
text.text = '';

beep = new sound.Sound({
    win: psychoJS.window,
    value: sounds,
    secs: 3,
  });

Each Frame

let theseKeys = psychoJS.eventManager.getKeys();
if (theseKeys.length > 0) {  // at least one key was pressed
  textAdd = theseKeys[theseKeys.length-1]; 
  }


if (textAdd === 'return') {
    textAdd = '';  // Add nothing
    continueRoutine = false;  // End routine (if that is what you want)
} else if (textAdd === 'space') {
    textAdd = ' ';  // Add a space
} else if (textAdd === 'backspace') {
    text.text = text.text.slice(0, -1);
    textAdd = undefined;
} else if (['lshift', 'rshift'].includes(textAdd)) {
    modify = true;
} else if (textAdd !== undefined) {
    if (modify) {
        text.text = text.text + textAdd.toUpperCase();
        modify = false;
    } else {
        text.text = text.text + textAdd
    }
    textAdd = undefined;
}


if ((mouse.getPressed()[2] !== 0)) {
    beep.play();
}

URL: https://run.pavlovia.org/hscheng/nonword_spelling/html

Thanks again!

@HungShao, yes in this instance this is happening because mouse.getPressed() records when a mouse button is clicked, not the current state of the mouse. So, after clicking the right mouse button, the play condition is always true and then the sound is continually played. An easy fix is to reset the mouse button after each right mouse button click. This is not necessarily the recommended way, however I do not see any other working method for resetting mouse clicks online:

if ((mouse.getPressed()[2] !== 0)) {
    beep.play();
    psychoJS.eventManager.getMouseInfo().buttons.pressed = [0,0,0]
}
    
1 Like

@dvbridges
Thank you so much!! This fixed the issue. One tiny follow-up, is it possible to switch from right-click to left-click?

Really appreciate your help!

Hi I figured this out. Thanks so much again!