psychopy / psychojs

PsychoJS is the online counterpart of the PsychoPy Python library
MIT License
165 stars 68 forks source link

Undefined error when playing sound in for loop #84

Closed ylrbc closed 4 years ago

ylrbc commented 4 years ago

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 sound.Sound, 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

peircej commented 4 years ago

Sorry, this issues list is really for bugs that need fixing in the library. This doesn't look like that so could I'm closing and suggest that you raise it on the forum instead? That said I wonder if the issue is just that you reach a j that's beyond the length of your list?