prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Overlapping recordings problem
  I am having a problem with mic.record and mic.stop - I am currently on psychopy 1.81.00, but I have had the same problem in earlier versions. I have written some code which records until the participant hits a key, or until a time-limit is reached. I am getting occasional truncated recordings or zero-length recordings - these occur when I test the code myself, so it's not just the participants being trigger-happy. I think the problem occurs when the timer on some past recording runs out, it stops the current recording. So say you set a recording running with a limit of 10 seconds, send a mic.stop() after 5 seconds, then start a new recording, that new recording will be stopped after 5 seconds, when the timer on the original recording runs out - it doesn't seem to be quite as neat as that in practice, which is confusing, but you can see this in action with something like the following little program. How often to occurs depends on how unlucky you are, but if you run through the for loop 10-15 times you will get some truncated recordings. 
  
  from psychopy import microphone,core,event, visual
  
  def recording(window,trialNum,mic):
      print('recording ' + str(trialNum))
      mic.reset()
      instructionText = visual.TextStim(window, text='Count to five, then press space',color="black",pos=(0,0.0),wrapWidth=2)
      instructionText.draw()
      window.flip()
      mic.record(7,block=False,filename=str(trialNum)+'.wav') #start recording
      event.waitKeys(maxWait='inf', keyList=['space']) #wait for a space from participant
      core.wait(0.1) #so you can hear the click of the spacebar
      window.flip()
      mic.stop() #stop the mic
      core.wait(0.1) #to get a flicker between screens
  # set up mic and window
  
  microphone.switchOn(sampleRate=44100)
  mic = microphone.AudioCapture()
  myWin = visual.Window((800,600), allowGUI=True,color='white')
  for t in range(100): #shouldn't need to do as many as 100 to get some truncated recordings!
      recording(myWin,t,mic)
  microphone.switchOff()
  core.quit()
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `psychopy/app/builder/components/microphone.py`
  Content:
  ```
  1 # Part of the PsychoPy library
  2 # Copyright (C) 2014 Jonathan Peirce
  3 # Distributed under the terms of the GNU General Public License (GPL).
  4 
  5 # Author: Jeremy R. Gray, 2012
  6 
  7 from _base import *
  8 from os import path
  9 from psychopy.app.builder import components #for getInitVals()
  10 
  11 thisFolder = path.abspath(path.dirname(__file__))#the absolute path to the folder containing this path
  12 iconFile = path.join(thisFolder,'microphone.png')
  13 tooltip = _translate('Microphone: basic sound capture (fixed onset & duration), okay for spoken words')
  14 
  15 _localized = {'stereo': _translate('Stereo')}
  16 
  17 class MicrophoneComponent(BaseComponent):
  18     """An event class for capturing short sound stimuli"""
  19     categories = ['Responses']
  20     def __init__(self, exp, parentName, name='mic_1',
  21                  startType='time (s)', startVal=0.0,
  22                  stopType='duration (s)', stopVal=2.0, startEstim='', durationEstim='',
  23                  stereo=False
  24                 ):
  25         super(MicrophoneComponent, self).__init__(exp, parentName, name=name,
  26                     startType=startType, startVal=startVal,
  27                     stopType=stopType, stopVal=stopVal,
  28                     startEstim=startEstim, durationEstim=durationEstim)
  29         self.type='Microphone'
  30         self.url="http://www.psychopy.org/builder/components/microphone.html"
  31         self.exp.requirePsychopyLibs(['microphone'])
  32         #params
  33         self.params['stereo']=Param(stereo, valType='bool',
  34             hint=_translate("Record two channels (stereo) or one (mono, smaller file)"),
  35             label=_localized['stereo'])
  36         self.params['stopType'].allowedVals = ['duration (s)']
  37         self.params['stopType'].hint = _translate('The duration of the recording in seconds; blank = 0 sec')
  38     def writeStartCode(self,buff):
  39         # filename should have date_time, so filename_wav should be unique
  40         buff.writeIndented("wavDirName = filename + '_wav'\n")
  41         buff.writeIndented("if not os.path.isdir(wavDirName):\n" +
  42                            "    os.makedirs(wavDirName)  # to hold .wav files\n")
  43     def writeRoutineStartCode(self,buff):
  44         inits = components.getInitVals(self.params)
  45         buff.writeIndented("%s = microphone.AdvAudioCapture(name='%s', saveDir=wavDirName, stereo=%s)\n" %(
  46             inits['name'], inits['name'], inits['stereo']))
  47     def writeFrameCode(self,buff):
  48         """Write the code that will be called every frame"""
  49         duration = "%s" % self.params['stopVal']  # type is code
  50         if not len(duration):
  51             duration = "0"
  52         # starting condition:
  53         buff.writeIndented("\n")
  54         buff.writeIndented("# *%s* updates\n" %(self.params['name']))
  55         self.writeStartTestCode(buff)  # writes an if statement
  56         buff.writeIndented("%(name)s.status = STARTED\n" %(self.params))
  57         buff.writeIndented("%s.record(sec=%s, block=False)  # start the recording thread\n" %
  58                             (self.params['name'], duration))
  59         buff.setIndentLevel(-1, relative=True)  # ends the if statement
  60         buff.writeIndented("\n")
  61         # these lines handle both normal end of rec thread, and user .stop():
  62         buff.writeIndented("if %(name)s.status == STARTED and not %(name)s.recorder.running:\n" % self.params)
  63         buff.writeIndented("    %s.status = FINISHED\n" % self.params['name'])
  64     def writeRoutineEndCode(self,buff):
  65         #some shortcuts
  66         name = self.params['name']
  67         if len(self.exp.flow._loopList):
  68             currLoop = self.exp.flow._loopList[-1] #last (outer-most) loop
  69         else:
  70             currLoop = self.exp._expHandler
  71 
  72         #write the actual code
  73         buff.writeIndented("# check responses\n" %self.params)
  74         buff.writeIndented("if not %(name)s.savedFile:\n"%self.params)
  75         buff.writeIndented("    %(name)s.savedFile = None\n" %(self.params))
  76         buff.writeIndented("# store data for %s (%s)\n" %(currLoop.params['name'], currLoop.type))
  77 
  78         #always add saved file name
  79         buff.writeIndented("%s.addData('%s.filename', %s.savedFile)\n" % (currLoop.params['name'],name,name))
  80         if currLoop.params['name'].val == self.exp._expHandler.name:
  81             buff.writeIndented("%s.nextEntry()\n" % self.exp._expHandler.name)
  82         # best not to do loudness / rms or other processing here
  83
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/psychopy/app/builder/components/microphone.py b/psychopy/app/builder/components/microphone.py
  --- a/psychopy/app/builder/components/microphone.py
  +++ b/psychopy/app/builder/components/microphone.py
  @@ -70,7 +70,8 @@
               currLoop = self.exp._expHandler
   
           #write the actual code
  -        buff.writeIndented("# check responses\n" %self.params)
  +        buff.writeIndented("# %(name)s stop & responses\n" %self.params)
  +        buff.writeIndented("%s.stop()  # sometimes helpful\n" % self.params['name'])
           buff.writeIndented("if not %(name)s.savedFile:\n"%self.params)
           buff.writeIndented("    %(name)s.savedFile = None\n" %(self.params))
           buff.writeIndented("# store data for %s (%s)\n" %(currLoop.params['name'], currLoop.type))
  
verification_info: {"golden_diff": "diff --git a/psychopy/app/builder/components/microphone.py b/psychopy/app/builder/components/microphone.py\n--- a/psychopy/app/builder/components/microphone.py\n+++ b/psychopy/app/builder/components/microphone.py\n@@ -70,7 +70,8 @@\n             currLoop = self.exp._expHandler\n \n         #write the actual code\n-        buff.writeIndented(\"# check responses\\n\" %self.params)\n+        buff.writeIndented(\"# %(name)s stop & responses\\n\" %self.params)\n+        buff.writeIndented(\"%s.stop()  # sometimes helpful\\n\" % self.params['name'])\n         buff.writeIndented(\"if not %(name)s.savedFile:\\n\"%self.params)\n         buff.writeIndented(\"    %(name)s.savedFile = None\\n\" %(self.params))\n         buff.writeIndented(\"# store data for %s (%s)\\n\" %(currLoop.params['name'], currLoop.type))\n", "issue": "Overlapping recordings problem\nI am having a problem with mic.record and mic.stop - I am currently on psychopy 1.81.00, but I have had the same problem in earlier versions. I have written some code which records until the participant hits a key, or until a time-limit is reached. I am getting occasional truncated recordings or zero-length recordings - these occur when I test the code myself, so it's not just the participants being trigger-happy. I think the problem occurs when the timer on some past recording runs out, it stops the current recording. So say you set a recording running with a limit of 10 seconds, send a mic.stop() after 5 seconds, then start a new recording, that new recording will be stopped after 5 seconds, when the timer on the original recording runs out - it doesn't seem to be quite as neat as that in practice, which is confusing, but you can see this in action with something like the following little program. How often to occurs depends on how unlucky you are, but if you run through the for loop 10-15 times you will get some truncated recordings. \n\nfrom psychopy import microphone,core,event, visual\n\ndef recording(window,trialNum,mic):\n    print('recording ' + str(trialNum))\n    mic.reset()\n    instructionText = visual.TextStim(window, text='Count to five, then press space',color=\"black\",pos=(0,0.0),wrapWidth=2)\n    instructionText.draw()\n    window.flip()\n    mic.record(7,block=False,filename=str(trialNum)+'.wav') #start recording\n    event.waitKeys(maxWait='inf', keyList=['space']) #wait for a space from participant\n    core.wait(0.1) #so you can hear the click of the spacebar\n    window.flip()\n    mic.stop() #stop the mic\n    core.wait(0.1) #to get a flicker between screens\n# set up mic and window\n\nmicrophone.switchOn(sampleRate=44100)\nmic = microphone.AudioCapture()\nmyWin = visual.Window((800,600), allowGUI=True,color='white')\nfor t in range(100): #shouldn't need to do as many as 100 to get some truncated recordings!\n    recording(myWin,t,mic)\nmicrophone.switchOff()\ncore.quit()\n\n", "before_files": [{"content": "# Part of the PsychoPy library\n# Copyright (C) 2014 Jonathan Peirce\n# Distributed under the terms of the GNU General Public License (GPL).\n\n# Author: Jeremy R. Gray, 2012\n\nfrom _base import *\nfrom os import path\nfrom psychopy.app.builder import components #for getInitVals()\n\nthisFolder = path.abspath(path.dirname(__file__))#the absolute path to the folder containing this path\niconFile = path.join(thisFolder,'microphone.png')\ntooltip = _translate('Microphone: basic sound capture (fixed onset & duration), okay for spoken words')\n\n_localized = {'stereo': _translate('Stereo')}\n\nclass MicrophoneComponent(BaseComponent):\n    \"\"\"An event class for capturing short sound stimuli\"\"\"\n    categories = ['Responses']\n    def __init__(self, exp, parentName, name='mic_1',\n                 startType='time (s)', startVal=0.0,\n                 stopType='duration (s)', stopVal=2.0, startEstim='', durationEstim='',\n                 stereo=False\n                ):\n        super(MicrophoneComponent, self).__init__(exp, parentName, name=name,\n                    startType=startType, startVal=startVal,\n                    stopType=stopType, stopVal=stopVal,\n                    startEstim=startEstim, durationEstim=durationEstim)\n        self.type='Microphone'\n        self.url=\"http://www.psychopy.org/builder/components/microphone.html\"\n        self.exp.requirePsychopyLibs(['microphone'])\n        #params\n        self.params['stereo']=Param(stereo, valType='bool',\n            hint=_translate(\"Record two channels (stereo) or one (mono, smaller file)\"),\n            label=_localized['stereo'])\n        self.params['stopType'].allowedVals = ['duration (s)']\n        self.params['stopType'].hint = _translate('The duration of the recording in seconds; blank = 0 sec')\n    def writeStartCode(self,buff):\n        # filename should have date_time, so filename_wav should be unique\n        buff.writeIndented(\"wavDirName = filename + '_wav'\\n\")\n        buff.writeIndented(\"if not os.path.isdir(wavDirName):\\n\" +\n                           \"    os.makedirs(wavDirName)  # to hold .wav files\\n\")\n    def writeRoutineStartCode(self,buff):\n        inits = components.getInitVals(self.params)\n        buff.writeIndented(\"%s = microphone.AdvAudioCapture(name='%s', saveDir=wavDirName, stereo=%s)\\n\" %(\n            inits['name'], inits['name'], inits['stereo']))\n    def writeFrameCode(self,buff):\n        \"\"\"Write the code that will be called every frame\"\"\"\n        duration = \"%s\" % self.params['stopVal']  # type is code\n        if not len(duration):\n            duration = \"0\"\n        # starting condition:\n        buff.writeIndented(\"\\n\")\n        buff.writeIndented(\"# *%s* updates\\n\" %(self.params['name']))\n        self.writeStartTestCode(buff)  # writes an if statement\n        buff.writeIndented(\"%(name)s.status = STARTED\\n\" %(self.params))\n        buff.writeIndented(\"%s.record(sec=%s, block=False)  # start the recording thread\\n\" %\n                            (self.params['name'], duration))\n        buff.setIndentLevel(-1, relative=True)  # ends the if statement\n        buff.writeIndented(\"\\n\")\n        # these lines handle both normal end of rec thread, and user .stop():\n        buff.writeIndented(\"if %(name)s.status == STARTED and not %(name)s.recorder.running:\\n\" % self.params)\n        buff.writeIndented(\"    %s.status = FINISHED\\n\" % self.params['name'])\n    def writeRoutineEndCode(self,buff):\n        #some shortcuts\n        name = self.params['name']\n        if len(self.exp.flow._loopList):\n            currLoop = self.exp.flow._loopList[-1] #last (outer-most) loop\n        else:\n            currLoop = self.exp._expHandler\n\n        #write the actual code\n        buff.writeIndented(\"# check responses\\n\" %self.params)\n        buff.writeIndented(\"if not %(name)s.savedFile:\\n\"%self.params)\n        buff.writeIndented(\"    %(name)s.savedFile = None\\n\" %(self.params))\n        buff.writeIndented(\"# store data for %s (%s)\\n\" %(currLoop.params['name'], currLoop.type))\n\n        #always add saved file name\n        buff.writeIndented(\"%s.addData('%s.filename', %s.savedFile)\\n\" % (currLoop.params['name'],name,name))\n        if currLoop.params['name'].val == self.exp._expHandler.name:\n            buff.writeIndented(\"%s.nextEntry()\\n\" % self.exp._expHandler.name)\n        # best not to do loudness / rms or other processing here\n", "path": "psychopy/app/builder/components/microphone.py"}], "after_files": [{"content": "# Part of the PsychoPy library\n# Copyright (C) 2014 Jonathan Peirce\n# Distributed under the terms of the GNU General Public License (GPL).\n\n# Author: Jeremy R. Gray, 2012\n\nfrom _base import *\nfrom os import path\nfrom psychopy.app.builder import components #for getInitVals()\n\nthisFolder = path.abspath(path.dirname(__file__))#the absolute path to the folder containing this path\niconFile = path.join(thisFolder,'microphone.png')\ntooltip = _translate('Microphone: basic sound capture (fixed onset & duration), okay for spoken words')\n\n_localized = {'stereo': _translate('Stereo')}\n\nclass MicrophoneComponent(BaseComponent):\n    \"\"\"An event class for capturing short sound stimuli\"\"\"\n    categories = ['Responses']\n    def __init__(self, exp, parentName, name='mic_1',\n                 startType='time (s)', startVal=0.0,\n                 stopType='duration (s)', stopVal=2.0, startEstim='', durationEstim='',\n                 stereo=False\n                ):\n        super(MicrophoneComponent, self).__init__(exp, parentName, name=name,\n                    startType=startType, startVal=startVal,\n                    stopType=stopType, stopVal=stopVal,\n                    startEstim=startEstim, durationEstim=durationEstim)\n        self.type='Microphone'\n        self.url=\"http://www.psychopy.org/builder/components/microphone.html\"\n        self.exp.requirePsychopyLibs(['microphone'])\n        #params\n        self.params['stereo']=Param(stereo, valType='bool',\n            hint=_translate(\"Record two channels (stereo) or one (mono, smaller file)\"),\n            label=_localized['stereo'])\n        self.params['stopType'].allowedVals = ['duration (s)']\n        self.params['stopType'].hint = _translate('The duration of the recording in seconds; blank = 0 sec')\n    def writeStartCode(self,buff):\n        # filename should have date_time, so filename_wav should be unique\n        buff.writeIndented(\"wavDirName = filename + '_wav'\\n\")\n        buff.writeIndented(\"if not os.path.isdir(wavDirName):\\n\" +\n                           \"    os.makedirs(wavDirName)  # to hold .wav files\\n\")\n    def writeRoutineStartCode(self,buff):\n        inits = components.getInitVals(self.params)\n        buff.writeIndented(\"%s = microphone.AdvAudioCapture(name='%s', saveDir=wavDirName, stereo=%s)\\n\" %(\n            inits['name'], inits['name'], inits['stereo']))\n    def writeFrameCode(self,buff):\n        \"\"\"Write the code that will be called every frame\"\"\"\n        duration = \"%s\" % self.params['stopVal']  # type is code\n        if not len(duration):\n            duration = \"0\"\n        # starting condition:\n        buff.writeIndented(\"\\n\")\n        buff.writeIndented(\"# *%s* updates\\n\" %(self.params['name']))\n        self.writeStartTestCode(buff)  # writes an if statement\n        buff.writeIndented(\"%(name)s.status = STARTED\\n\" %(self.params))\n        buff.writeIndented(\"%s.record(sec=%s, block=False)  # start the recording thread\\n\" %\n                            (self.params['name'], duration))\n        buff.setIndentLevel(-1, relative=True)  # ends the if statement\n        buff.writeIndented(\"\\n\")\n        # these lines handle both normal end of rec thread, and user .stop():\n        buff.writeIndented(\"if %(name)s.status == STARTED and not %(name)s.recorder.running:\\n\" % self.params)\n        buff.writeIndented(\"    %s.status = FINISHED\\n\" % self.params['name'])\n    def writeRoutineEndCode(self,buff):\n        #some shortcuts\n        name = self.params['name']\n        if len(self.exp.flow._loopList):\n            currLoop = self.exp.flow._loopList[-1] #last (outer-most) loop\n        else:\n            currLoop = self.exp._expHandler\n\n        #write the actual code\n        buff.writeIndented(\"# %(name)s stop & responses\\n\" %self.params)\n        buff.writeIndented(\"%s.stop()  # sometimes helpful\\n\" % self.params['name'])\n        buff.writeIndented(\"if not %(name)s.savedFile:\\n\"%self.params)\n        buff.writeIndented(\"    %(name)s.savedFile = None\\n\" %(self.params))\n        buff.writeIndented(\"# store data for %s (%s)\\n\" %(currLoop.params['name'], currLoop.type))\n\n        #always add saved file name\n        buff.writeIndented(\"%s.addData('%s.filename', %s.savedFile)\\n\" % (currLoop.params['name'],name,name))\n        if currLoop.params['name'].val == self.exp._expHandler.name:\n            buff.writeIndented(\"%s.nextEntry()\\n\" % self.exp._expHandler.name)\n        # best not to do loudness / rms or other processing here\n", "path": "psychopy/app/builder/components/microphone.py"}]}