Reply To: Issues playing audio files – project works in Firefox but not Chrome

PennController for IBEX Forums Bug Report Issues playing audio files – project works in Firefox but not Chrome Reply To: Issues playing audio files – project works in Firefox but not Chrome

#8163
Jeremy
Keymaster

Hi Aiden,

I’m sorry for not catching this problem: I use Firefox as my default browser, and even though I usually check that things also work on Chrome, I never tested playing back the same audio file within a single trial in two different Audio elements on Chrome. What happens is, browsers usually prevent webpages from automatically playing back audio/video files until the user has interacted with the page. Both Firefox and Chrome do that, which messes with the preloading of the audio files. For some reason, when that happens but Firefox still ultimately manages to preload an audio file, PennController notifies all Audio elements using the same audio file that it’s been preloaded. When the same thing happens on Chrome, however, only one of the two elements gets notified

I’ll work on fixing that in the next release of PennController. In the meantime, you can override the definition of the Audio element to make it wait for a click on (= interaction with) the page before preloading the audios. I tested this solution on Chrome and it seems to work well

The very first thing to do is insert an intro trial to make participants click on the page before they get to the first trial, so that the browser detects an interaction with the page and can safely start preloading the audio files. Something like:

Sequence("intro","trials_1.2")

newTrial("intro", newButton("Start").print().wait() )

Then, you need to download this file (use your browser’s Save function–make sure to keep the filename PennElement_audio.js). Upload this file to your project’s Modules folder: it will effectively override the Audio element defined in your project’s copy of PennController.js (which will give you an error in the debugger saying “Element type Audio defined more than once” when you run your experiment, but you can just ignore it)

Now, you’ll need to make some edits to that file. First, you should add this line at the very top: const hasClicked = new Promise(r=>document.addEventListener("mousedown", r));

Then, since you are using PennController 2.0, you should delete (or comment out) the block of lines starting with this.resource = PennEngine.resources.new(file, function(uri, resolve){ up to (the first occurrence of) }, addHostURLs);. Notice all the lines coming after that prefixed with //, starting with // this.resource = PennEngine.resources.fetch(file, function(resolve){: you need to uncomment them all (ie. delete // at the beginning) up to and including // }, addHostURLs);

Finally, replace this.resource = PennEngine.resources.fetch(file, function(resolve){ with this.resource = PennEngine.resources.fetch(file, async function(resolve){ and just after that line, and before this.object = new Audio(); // Creation of the audio using the resource's value, insert a line with just await hasClicked;

Once you’ve proceeded to those edits, the first lines of your copy of PennElement_audio.js should be:

const hasClicked = new Promise(r=>document.addEventListener("mousedown", r));

// AUDIO element
/* $AC$ PennController.newAudio(name,file) Creates a new Audio element $AC$ */
/* $AC$ PennController.getAudio(name) Retrieves an existing Audio element $AC$ */
window.PennController._AddElementType("Audio", function(PennEngine) {

    const RATIO_PRELOADED = 0.95;

    // This is executed when Ibex runs the script in data_includes (not a promise, no need to resolve)
    this.immediate = function(id, file){
        if (typeof id == "string" && file===undefined)
            file = id;
        let addHostURLs = !file.match(/^http/i);

        this.resource = PennEngine.resources.fetch(file, async function(resolve){
          await hasClicked;
          this.object = new Audio();               // Creation of the audio using the resource's value

Take your experiment in Chrome, and it should now preload fine

Let me know if you encounter issues or have any questions

Jeremy