Loading sounds on the fly

URL of experiment: https://pavlovia.org/theoceanistea/gap-detection

Description of the problem:
I found out about being able to load resources as needed. This seems like a solution to the problem of not wanting the participant to load every wav file they might need to hear before starting the experiment.

When I load the resource noise.wav from the html folder at the head of the program, it plays. But when I load it on the fly using downloadResources, it gives me the error,

Unfortunately we encountered the following error:

  • when finding a player for the sound
  • could not find an appropriate player.

Try to run the experiment again. If the error persists, contact the experiment designer.

How can I avoid this?

Thanks,
Jon

1 Like

Can anyone help with this one? I’ve tried switching to mp3, but same error.

Ok, I finally fixed it. I think the task was going on before the loading finished. My fix was to load the sound file during the previous routine, which lasts for 5+ seconds and apparently leaves enough time for the file to load.

I was wrong. The fixed that actually fixed it was changing to the command

psychoJS._serverManager.downloadResources

rather than psychoJS.downloadResources. I think there’s a problem with the source code defining psychoJS.downloadResources? Maybe a missing underscore? I’m just learning javascript, so I’m not sure.

How does this actually work?

I’d like to suppress downloading all the resources at the beginning of the experiment and then download the set of 7 wav files I actually need during the experiment.

I’d like to be able to do this via code components rather than editing the js files directly.

Best wishes,

Wakefield

Hi Wakefield,
I’m still a little confused about this, but it looks like everything in the html/resources folder is automatically downloaded (unless you change the js code), and everything else is ignored. If you then insert

psychoJS._serverManager.downloadResources([
{ name: [filename], path: [filename+(path relative to html folder) OR (web address)] }
]);

at the beginning of a routine, you can use the file [filename] after that. BUT… I’ve been pulling files from another website, and it takes time to get the file, and the code does not wait for the file to load, so there needs to be a sufficient delay between the download call and the use of the file.

That’s all I’ve figured out so far.

Thanks for your help earlier, hope I’m being helpful here!
Jon

PS. Now I’m not sure there’s actually a problem with the regular psychoJS.downloadResources command – I think it was just a problem with it blocking as described here:

But now that I’ve got it working, I’ll just stick with psychoJS._serverManager.downloadResources. Call me superstitious.

I’ve tried
psychoJS._serverManager.downloadResources([
{ name: [ā€œ01F_HA_O.jpgā€], path: [(ā€œNim-Face-Stimuli/01F_HA_O.jpgā€)] }
]);

Any ideas?

I first tried to put the images in a sub folder from the Python code and used …/Nim-Face-Stimuli/01F_HA_O.jpg but then I thought that maybe the files have to be in the html folder or below it.

I get an unknown resource error:

  • when setting the image of ImageStim: images
  • when getting the value of resource: Nim-Face-Stimuli/01F_HA_O.jpg
  • unknown resource

Sorted. I needed

 psychoJS.downloadResources([
{ name: '01F_HA_O.jpg', path: 'Nim-Face-Stimuli/01F_HA_O.jpg' },
{ name: '01F_NE_C.jpg', path: 'Nim-Face-Stimuli/01F_NE_C.jpg' }
]);

The error occurs when it’s specified twice.

I’ve also confirmed that the files don’t need to be in/below the html folder

1 Like

Hi,

This topic is very helpful for my case too

However, the auditory files I would like to load are listed in a specific column of a .csv file.
I tried to run the function with the following code

psychoJS.downloadResources([
{ name: 'XXX.csv', path: 'YYY/XXX.csv' },
]);

However, it does not work.

Do I need to specify each file in the psychoJS.downloadResources()?
Or is there any easy way to load all the files listed in a specific column of a .csv file.

Thanks!

If you load the contents of your csv intro arrays or a Trial Handler then you could set up a loop to append dictionary entries so you can use downloadResources. The code you’ve written looks like it’s asking PsychoJS to download the csv file, not things references in it.

Thanks @wakecarter!
Would you mind to provide a reference or an example? Sorry that I am very new to Javascript.
Thanks in advance!

Here’s some JS code that downloads the last three sound files from each of two arrays.

shuffle(naturalSpeech);
shuffle(repeatedSpeech);

wordsLeft = naturalSpeech.length;

psychoJS.downloadResources([
{ name: (naturalSpeech[wordsLeft-1]), path: ("../CS/" + naturalSpeech[wordsLeft-1]) },
{ name: (naturalSpeech[wordsLeft-2]), path: ("../CS/" + naturalSpeech[wordsLeft-2]) },
{ name: (naturalSpeech[wordsLeft-3]), path: ("../CS/" + naturalSpeech[wordsLeft-3]) },
{ name: (repeatedSpeech[wordsLeft-1]), path: ("../SS/" + repeatedSpeech[wordsLeft-1]) },
{ name: (repeatedSpeech[wordsLeft-2]), path: ("../SS/" + repeatedSpeech[wordsLeft-2]) },
{ name: (repeatedSpeech[wordsLeft-3]), path: ("../SS/" + repeatedSpeech[wordsLeft-3]) }
]);


Looking at it now, I’m not sure I needed wordsLeft because [-1] already refers to the final item in an array.

If you aren’t sure how to load csv/Excel files into an array, please look at my template file. Brookes Template 2020

You should also be able to create a loop to build the dictionary,

e.g. Begin Experiment = resourceList = []

Begin Routine (within a loop)
resourceList.push({ name: (var1+".extension"), path: ("…/stimulusFolder/"+var1+".extension")});

then (but make sure you give time for them to load)

psychoJS.downloadResources(resourceList);

1 Like

Thanks it works!

A little addition to the approach above, since I’ll point @Zhaleh to this thread. A nice way of checking whether a resource has been downloaded is as followed:

Step 1. Have a routine for downloading resources, maybe add a text like ā€œOne moment pleaseā€ to keep your participant informed.

Step 2. Add a code component.
Step 2a. In the begin routine tab of that code component, call PsychoJS to download the resource. For example:

psychoJS.downloadResources([
  { name: 'my_sound.mp3', path: 'sounds/my_sound.mp3' }
]);

Step 2b. In the each frame tab, keep checking whether the sound has downloaded. Once it does, finish the routine, and you can use the sound in a successive routine. Below we use the following trick: if psychoJS.serverManager.getResource('my_sound.mp3') does not throw an error, the resource is available.

try {
    psychoJS.serverManager.getResource('my_sound.mp3');
    continueRoutine = false;
} catch (e) {}

The example above is an adaptation of: Thomas Pronk / demo_font Ā· GitLab

1 Like