def sound(self,
              filename,         # the sound file name to play (preferably a relative path)
              block=False,      # optionally wait until the sound has finished playing before returning from this function
              # optional parameters
              volume=0.1,       # the volume of the sound (between 0 and 1)
              direction=0.0,    # the balance; may be a number between -1 (hard left) and 1 (hard right), or an angle if surround=True
              playrate=1.0,     # the playrate of the sound (changes pitch and time)
              timeoffset=0.0,   # time offset into the file
              looping=False,    # whether the sound should be looping; can be turned off by calling .stop() on the return value of this function
              loopcount=None,   # optionally the number of repeats if looping
              surround=False,   # if True, the direction will go from -Pi/2 to Pi/2
              ):
        """Play a sound in a particular location."""
        if surround:            
            if self.audio3d is None:
                self.audio3d = self._engine.direct.showbase.Audio3DManager.Audio3DManager(self._engine.base.sfxManagerList[0],None)
            obj = self.audio3d.loadSfx(filename)
            self._to_destroy.append(obj)
            obj.set3dAttributes(1.0*math.sin(direction),1.0*math.cos(direction),0.0,0.0,0.0,0.0)
            obj.setVolume(volume)
        else:
            obj = self._engine.base.loader.loadSfx(filename)
            self._to_destroy.append(obj)
            obj.setVolume(volume)
            obj.setBalance(direction)
        length = obj.length()
        if loopcount is not None:
            obj.setLoopCount(loopcount)
            length *= loopcount
        if looping:
            obj.setLoop(True)
            length = 100000
        if timeoffset > 0.0:
            obj.setTime(timeoffset)
            length -= timeoffset
        obj.setPlayRate(playrate)
        length *= playrate
        obj.play()
        if self.implicit_markers:
            self.marker(246)
        if block:
            self.sleep(length)
            self._destroy_object(obj,247)            
        else:
            self._engine.base.taskMgr.doMethodLater(length, self._destroy_object, 'ConvenienceFunctions, end_sound', extraArgs=[None,247])
            return obj
dataset/ETHPy150Open sccn/SNAP/src/framework/basicstimuli.py/BasicStimuli.sound/original