psychopy.org | Reference | Downloads | Github

How to properly loop a sound stimulus for certain amount of time?

I was trying to create a function that loops a sound file using psychopy sound class in a way similar to how it can be achieved through the pygame mixer below.

from psychopy import visual,core
from pygame import mixer
win = visual.Window(fullscr = False, size = (1200,900),
                    color = (-1.0,-1.0,-1.0), units = 'norm', monitor = 'testMonitor')
text= visual.TextStim(win, text ='test', height = 0.06, color = 'white',pos = (0,0))
def play_sound(timing):
    mySound = mixer.Sound('sound_file.wav')
    duration = core.CountdownTimer(timing)
    duration.reset()
    # loop the sound until duration reaches 0
    while duration.getTime() > 0:
        mySound.play(loops=-1)
        text.draw()
        win.flip()
    mySound.stop()
mixer.init()
play_sound(10)

But when I tried to achieve it by implementing the psychopy sound class, I kelt getting the error below.

from psychopy import sound,visual,core
win = visual.Window(fullscr = False, size = (1200,900),
                    color = (-1.0,-1.0,-1.0), units = 'norm', monitor = 'testMonitor')
text= visual.TextStim(win, text ='test', height = 0.06, color = 'white',pos = (0,0))
def play_sound(timing):
    mySound = sound.Sound(value='sound_file.wav',loops=-1)
    duration = core.CountdownTimer(timing)
    duration.reset()
    while duration.getTime() > 0:
        mySound.play()
        text.draw()
        win.flip()
    mySound.stop()

play_sound(10)

From cffi callback <function _StreamBase.init..callback_ptr at 0x000001B81DC06828>:
Traceback (most recent call last):
File “C:\Program Files\Python37\lib\site-packages\sounddevice.py”, line 741, in callback_ptr
return _wrap_callback(callback, data, frames, time, status)
File “C:\Program Files\Python37\lib\site-packages\sounddevice.py”, line 2517, in _wrap_callback
callback(*args)
File “C:\Program Files\Python37\lib\site-packages\psychopy\sound\backend_sounddevice.py”, line 201, in callback
dat *= thisSound.volume # Set the volume block by block
TypeError: unsupported operand type(s) for *=: ‘NoneType’ and ‘float’

I didn’t find much example about how the sound class can be operated in this way in the documentation. Thanks for help!

That’s an interesting bug, for sure. I’ve never needed loops and I suspect it’s actually broken. I’ve gotten sound looping to work just fine in some of my projects by checking the sound status and just calling “play” if the status indicates it’s not currently playing. I’ve modified your code to use my approach (including initializing the sound object a little differently), see if it works any better.

from psychopy import sound,visual,core
from psychopy.constants import STARTED, PLAYING
win = visual.Window(fullscr = False, size = (1200,900),
                    color = (-1.0,-1.0,-1.0), units = 'norm', monitor = 'testMonitor')
text= visual.TextStim(win, text ='test', height = 0.06, color = 'white',pos = (0,0))
def play_sound(timing):
    mySound = sound.Sound('sound_file.wav')
    duration = core.CountdownTimer(timing)
    duration.reset()
    while duration.getTime() > 0:
        if mySound.status not in [STARTED, PLAYING]:
            mySound.play()
        text.draw()
        win.flip()
    mySound.stop()

play_sound(10)
1 Like

Thanks for your help!