PsychoJS: undefined error when playing sound in for loop

URL of experiment: https://run.pavlovia.org/ylrbc/fyp-test/html/

Description of the problem:

Hi PsychoJS,

I am trying to manually code an experiment and got some issues with playing sound. I got this problem which I cannot figure out. It would be great if you can let me know what I did wrong and potentially how to fix it. Much appreciated!

Basically I wanted to loop through a few sound files with an interval. The following code snippets of playing sound playing was adapted from the generated code from PsychoPy and put into frame-updating function. “aud_bep” was initialized as an array of 9 sound.Sound objects, and each of them is set to a file. The status was set to NOT_STARTED before the frame-updating function.

I got an “undefined” error when I try to use for loop:

for (j=0; j<2; j++) {
    if (t >=  j*gap + 0.25 && aud_bep[j].status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        aud_bep[j].tStart = t;  // (not accounting for frame time here)
        aud_bep[j].frameNStart = frameN;  // exact frame index

        psychoJS.window.callOnFlip(function(){ aud_bep[j].play(); });  // screen flip
        aud_bep[j].status = PsychoJS.Status.STARTED;
    }
    if (t >= (aud_bep[j].getDuration() + aud_bep[j].tStart)     && aud_bep[j].status === PsychoJS.Status.STARTED) {
        aud_bep[j].stop();  // stop the sound (if longer than duration)
        aud_bep[j].status = PsychoJS.Status.FINISHED;
    }
}

This is the error message in console:

TypeError: "aud_bep[j] is undefined" core-2020.1.js:1437:12
    execTrialFrame https://run.pavlovia.org/ylrbc/fyp-test/html/test.js:617
    render https://run.pavlovia.org/ylrbc/fyp-test/html/lib/core-2020.1.js:669
    update https://run.pavlovia.org/ylrbc/fyp-test/html/lib/util-2020.1.js:1063

FATAL unknown | {} log4javascript.min.js:1:40074
    append https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
    doAppend https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
    callAppenders https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
    log https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
    fatal https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
    dialog https://run.pavlovia.org/ylrbc/fyp-test/html/lib/core-2020.1.js:920
    onerror https://run.pavlovia.org/ylrbc/fyp-test/html/lib/core-2020.1.js:1438

But the sound files were correctly played if I put everything outside the loop. For example:

j = 0;
if (t >= j*gap + 0.25 && aud_bep[j].status === PsychoJS.Status.NOT_STARTED) {
    // keep track of start time/frame for later
    aud_bep[j].tStart = t;  // (not accounting for frame time here)
    aud_bep[j].frameNStart = frameN;  // exact frame index

    psychoJS.window.callOnFlip(function(){ aud_bep[j].play(); });  // screen flip
    aud_bep[j].status = PsychoJS.Status.STARTED;
}
if (t >= (aud_bep[j].getDuration() + aud_bep[j].tStart)     && aud_bep[j].status === PsychoJS.Status.STARTED) {
    aud_bep[j].stop();  // stop the sound (if longer than duration)
    aud_bep[j].status = PsychoJS.Status.FINISHED;
}

if (t >= 1*gap + 0.25 && aud_bep[1].status === PsychoJS.Status.NOT_STARTED) {
    // keep track of start time/frame for later
    aud_bep[1].tStart = t;  // (not accounting for frame time here)
    aud_bep[1].frameNStart = frameN;  // exact frame index

    psychoJS.window.callOnFlip(function(){ aud_bep[1].play(); });  // screen flip
    aud_bep[1].status = PsychoJS.Status.STARTED;
}
if (t >= (aud_bep[1].getDuration() + aud_bep[1].tStart)     && aud_bep[1].status === PsychoJS.Status.STARTED) {
    aud_bep[1].stop();  // stop the sound (if longer than duration)
    aud_bep[1].status = PsychoJS.Status.FINISHED;
}

Also, if I use “j” to index second object:

j = 0;
if (t >= j*gap + 0.25 && aud_bep[j].status === PsychoJS.Status.NOT_STARTED) {
    // keep track of start time/frame for later
    aud_bep[j].tStart = t;  // (not accounting for frame time here)
    aud_bep[j].frameNStart = frameN;  // exact frame index

    psychoJS.window.callOnFlip(function(){ aud_bep[j].play(); });  // screen flip
    aud_bep[j].status = PsychoJS.Status.STARTED;
}
if (t >= (aud_bep[j].getDuration() + aud_bep[j].tStart)     && aud_bep[j].status === PsychoJS.Status.STARTED) {
    aud_bep[j].stop();  // stop the sound (if longer than duration)
    aud_bep[j].status = PsychoJS.Status.FINISHED;
}
j = 1;
if (t >= j*gap + 0.25 && aud_bep[j].status === PsychoJS.Status.NOT_STARTED) {
    // keep track of start time/frame for later
    aud_bep[j].tStart = t;  // (not accounting for frame time here)
    aud_bep[j].frameNStart = frameN;  // exact frame index

    psychoJS.window.callOnFlip(function(){ aud_bep[j].play(); });  // screen flip
    aud_bep[j].status = PsychoJS.Status.STARTED;
}
if (t >= (aud_bep[j].getDuration() + aud_bep[j].tStart)     && aud_bep[j].status === PsychoJS.Status.STARTED) {
    aud_bep[j].stop();  // stop the sound (if longer than duration)
    aud_bep[j].status = PsychoJS.Status.FINISHED;
}

only one file will be played. But there is no error message in this case.

It’s likely that I did something stupid but I couldn’t figure it out for 2 days. If you have some time to take a look, it’d be really awesome. Please let me know if more information is needed.

Thanks!
Yu Li

1 Like

Did you solve this issue by any chance?