Experiment plays loud tone instead of wav file (likely psychoJS issues with custom stimuli randomisation code)

URL of experiment: Virginia Penhune / Melody_combined · GitLab

I’ve added in some custom code to quasi-randomize stimulus presentation so the same stimulus type isn’t presented too many times in a row. (See this issue)

Seems to work offline but online I just get a loud tone in place of my stimuli (wav files). I suspect there is an issue with some of the auto conversion from python to JS. (Unless I need to pass full file paths of my stimuli? Since I’m not getting my file names from a loop. Only other thing I can think of.)

I will try present the code here but it’s a bit of a mess. I appreciate any help. I’ve tried to make this clear but if I can present it in a better way or give more detail let me know. I haven’t mentioned the structure of the experiment (e.g. loop placement, whether code is at start of experiment vs routine, etc.) because I suspect it’s just a typo in the JS code but I can give more detail if needed.

CODE:

This code creates some initial objects, loads in the data from a csv and also creates psychoJS equivalents for range and append functions (in the JS code only).

Python:

stimulus_list=[]
stim_type=[]
index = [x for x in range(48)]

psychoJS:

function range(size, startAt = 0) {
    return [...Array(size).keys()].map(i => i + startAt);
}

Array.prototype.append = [].push

stimulus_list = [];
stim_type = [];
index = function () {
    var _pj_a = [], _pj_b = range(48);
    for (var _pj_c = 0, _pj_d = _pj_b.length; (_pj_c < _pj_d); _pj_c += 1) {
        var x = _pj_b[_pj_c];
        _pj_a.push(x);
    }
    return _pj_a;
}
.call(this);

Python:

stimulus_list.append(str(melody))
stim_type.append(str(type_stim))

psychoJS:

stimulus_list.append(melody.toString());
stim_type.append(type_stim.toString());



Here is the big one that does the randomization.
Python:

shuffle(index)
stim_type = [stim_type[i] for i in index]

# make sure the same target doesn't appear on consecutive trials
double_stim = False
list_ok = False

while list_ok == False:
    for i in range(len(stim_type) - 1):
        # check for 4 equal neighbours:
        if stim_type[i] == stim_type[i + 1] and stim_type[i + 1] == stim_type[i + 2] and stim_type[i + 2] == stim_type[i + 3]:
            break  # can stop checking on this run
    if double_stim == True:
        shuffle(index)  # try a new order
        double_stim = False
    else:
        list_ok = True  # stop loop

stimulus_list = [stimulus_list[i] for i in index]
stimulus = stimulus_list[0]
i = 0

psychoJS:

util.shuffle(index);
stim_type = function () {
    var _pj_a = [], _pj_b = index;
    for (var _pj_c = 0, _pj_d = _pj_b.length; (_pj_c < _pj_d); _pj_c += 1) {
        var i = _pj_b[_pj_c];
        _pj_a.push(stim_type[i]);
    }
    return _pj_a;
}
.call(this);
double_stim = false;
list_ok = false;
while ((list_ok === false)) {
    for (var i = 0, _pj_a = (stim_type.length - 1); (i < _pj_a); i += 1) {
        if ((((stim_type[i] === stim_type[(i + 1)]) && (stim_type[(i + 1)] === stim_type[(i + 2)])) && (stim_type[(i + 2)] === stim_type[(i + 3)]))) {
            break;
        }
    }
    if ((double_stim === true)) {
        util.shuffle(index);
        double_stim = false;
    } else {
        list_ok = true;
    }
}
stimulus_list = function () {
    var _pj_a = [], _pj_b = index;
    for (var _pj_c = 0, _pj_d = _pj_b.length; (_pj_c < _pj_d); _pj_c += 1) {
        var i = _pj_b[_pj_c];
        _pj_a.push(stimulus_list[i]);
    }
    return _pj_a;
}
.call(this);
stimulus = stimulus_list[0];
i = 0;

Lastly, this is the code that runs with the sound component. It selects each element from the randomized list. And then ‘$stimulus’ is the value set in the builder component. It also saves the order of the stimuli in the data.
Python:

thisExp.addData('stimuli', stimulus_list)

if melodies.thisN != 0:
    stimulus = stimulus_list[i+1]
    i = i+1

psychoJS:

psychoJS.experiment.addData("stimuli", stimulus_list);

if ((melodies.thisN !== 0)) {
    stimulus = stimulus_list[(i + 1)];
    i = (i + 1);
}

Have you added the sound files in Experiment Settings / Online?

mp3 works better than wav online, but wav should work on most browsers.

The sound files are in the html/resources folder online, if that’s what you mean.

This doesn’t work online. You need to replace the loop name with “snapshot” on the JS side in a Both component.

Hi @wakecarter Thanks for your help.

I’m not quite sure hwat you mean.

Should if ((melodies.thisN !== 0)) become

if ((snapshot.thisN !== 0))

OR

if ((snapshot !== 0))

Both of these give an error saying snapshot is not defined

I also tried if ((trials !== 0)) based on the crib sheet. Didn’t get an error but got the loud tone instead of the audio files again.

Note the experiment is using 2020.1

In 2020.1 you should use trials.thisN instead of snapshot.thisN on the JS side.

That seemed to do something! Now my first stimulus plays but then in the next trial it’s just the loud tone again.

if ((trials.thisN !== 0)) {
    stimulus = stimulus_list[(i + 1)];
    i = (i + 1);
}

Could there be any other issue with this code? Now that I think of it, it’s odd that this changed anything because this code is only meant to activate after the first trial.

“stimulus” is given an initial value of stimulus_list[0] outside of the loop (this is what supposedly plays in my first trial). I also initialize “i” with a value of 0 outside this loop. (see large code chunk above). So after the initial value in the first trial, I’m trying to move along the index of my randomized stimulus list with each new trial.

I did run it a second time and got a different stimulus in the first trial, which hopefully indicates my randomization is working.

Why are you starting with stimulus_list[1] instead of stimulus_list[0] (the first element)? Indeed, why are you using stimulus = stimulus_list[trials.thisN] ?

So it plays the first stimulus and then not the second? Perhaps you should try setting the start time of the sound file to 1 second (for example) to give the wav file time to load.

I just looked at your psyexp file. I can’t see your code_JS component so I’m surprised you aren’t getting an append error (because you haven’t changed append to push either).

I included it in one of my other code components (I should probably make a dedicated code_JS component).

But I’ve realised there are some errors in my orignal Python code, so I was doomed from the start. I’ll work on this and thanks for your help so far! I will update this thread if I find anything useful.