# Pavlovia only plays 1st audio file (But Psychopy locally plays all audio)

**URL:** https://discourse.psychopy.org/t/pavlovia-only-plays-1st-audio-file-but-psychopy-locally-plays-all-audio/35935
**Category:** Online experiments
**Tags:** sound, pavlovia
**Created:** [August 1, 2023, 2:30am UTC](https://discourse.psychopy.org/t/pavlovia-only-plays-1st-audio-file-but-psychopy-locally-plays-all-audio/35935 "2023-08-01T02:30:19Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![yonder-psychling24](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.psychopy.org/yonder-psychling24/32/38942_2.png) [@yonder-psychling24](https://discourse.psychopy.org/u/yonder-psychling24)
#### Post date: [August 1, 2023, 2:30am UTC](https://discourse.psychopy.org/t/pavlovia-only-plays-1st-audio-file-but-psychopy-locally-plays-all-audio/35935/1 "2023-08-01T02:30:19Z")

</div>

Hi all,

When I run an experiment on Pavlovia, only the first audio file in the loop plays; the rest of the audio files are silent. There is no problem when I run the experiment locally on PsychoPy. This experiment posted here is a simplified version (it’s simply 2 audio files in a loop and nothing) to replicate the problem in a barebones format.

I’ve tried changing browsers and changing file type (wav to mp3).

Any help is very much appreciated!!!

I’ll put the code in below.

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

- Two\_Audiofile\_Experiment \*  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

import { core, data, sound, util, visual, hardware } from ‘./lib/psychojs-2023.2.0.js’;  
const { PsychoJS } = core;  
const { TrialHandler, MultiStairHandler } = data;  
const { Scheduler } = util;  
//some handy aliases as in the psychopy scripts;  
const { abs, sin, cos, PI: pi, sqrt } = Math;  
const { round } = util;

// store info about the experiment session:  
let expName = ‘Two\_AudioFile\_Experiment’; // from the Builder filename that created this script  
let expInfo = {  
‘participant’: `${util.pad(Number.parseFloat(util.randint(0, 999999)).toFixed(0), 6)}`,  
‘session’: ‘001’,  
};

// Start code blocks for ‘Before Experiment’  
// init psychoJS:  
const psychoJS = new PsychoJS({  
debug: true  
});

// open window:  
psychoJS.openWindow({  
fullscr: true,  
color: new util.Color([0,0,0]),  
units: ‘height’,  
waitBlanking: true  
});  
// schedule the experiment:  
psychoJS.schedule(psychoJS.gui.DlgFromDict({  
dictionary: expInfo,  
title: expName  
}));

const flowScheduler = new Scheduler(psychoJS);  
const dialogCancelScheduler = new Scheduler(psychoJS);  
psychoJS.scheduleCondition(function() { return (psychoJS.gui.dialogComponent.button === ‘OK’); }, flowScheduler, dialogCancelScheduler);

// flowScheduler gets run if the participants presses OK  
flowScheduler.add(updateInfo); // add timeStamp  
flowScheduler.add(experimentInit);  
const trialsLoopScheduler = new Scheduler(psychoJS);  
flowScheduler.add(trialsLoopBegin(trialsLoopScheduler));  
flowScheduler.add(trialsLoopScheduler);  
flowScheduler.add(trialsLoopEnd);

flowScheduler.add(quitPsychoJS, ‘’, true);

// quit if user presses Cancel in dialog box:  
dialogCancelScheduler.add(quitPsychoJS, ‘’, false);

psychoJS.start({  
expName: expName,  
expInfo: expInfo,  
resources: [  
// resources:  
{‘name’: ‘SimpleAudioExperiment.xlsx’, ‘path’: ‘SimpleAudioExperiment.xlsx’},  
{‘name’: ‘Sounds/AudioFile\_1.mp3’, ‘path’: ‘Sounds/AudioFile\_1.mp3’},  
{‘name’: ‘Sounds/AudioFile\_2.mp3’, ‘path’: ‘Sounds/AudioFile\_2.mp3’},  
]  
});

psychoJS.experimentLogger.setLevel(core.Logger.ServerLevel.EXP);

var currentLoop;  
var frameDur;  
async function updateInfo() {  
currentLoop = psychoJS.experiment; // right now there are no loops  
expInfo[‘date’] = util.MonotonicClock.getDateStr(); // add a simple timestamp  
expInfo[‘expName’] = expName;  
expInfo[‘psychopyVersion’] = ‘2023.2.0’;  
expInfo[‘OS’] = window.navigator.platform;

// store frame rate of monitor if we can measure it successfully  
expInfo[‘frameRate’] = psychoJS.window.getActualFrameRate();  
if (typeof expInfo[‘frameRate’] !== ‘undefined’)  
frameDur = 1.0 / Math.round(expInfo[‘frameRate’]);  
else  
frameDur = 1.0 / 60.0; // couldn’t get a reliable measure so guess

// add info from the URL:  
util.addInfoFromUrl(expInfo);

psychoJS.experiment.dataFileName = ((“.” + “/”) + `data/${expInfo["participant"]}_${expName}_${expInfo["date"]}`);  
psychoJS.experiment.field\_separator = ‘\t’;

return Scheduler.Event.NEXT;  
}

var trialClock;  
var sound\_1;  
var globalClock;  
var routineTimer;  
async function experimentInit() {  
// Initialize components for Routine “trial”  
trialClock = new util.Clock();  
sound\_1 = new sound.Sound({  
win: psychoJS.window,  
value: ‘A’,  
secs: (- 1),  
});  
sound\_1.setVolume(3.0);  
// Create some handy timers  
globalClock = new util.Clock(); // to track the time since experiment started  
routineTimer = new util.CountdownTimer(); // to track time remaining of each (non-slip) routine

return Scheduler.Event.NEXT;  
}

var trials;  
function trialsLoopBegin(trialsLoopScheduler, snapshot) {  
return async function() {  
TrialHandler.fromSnapshot(snapshot); // update internal variables (.thisN etc) of the loop

```
// set up handler to look after randomisation of conditions etc
trials = new TrialHandler({
  psychoJS: psychoJS,
  nReps: 1, method: TrialHandler.Method.RANDOM,
  extraInfo: expInfo, originPath: undefined,
  trialList: 'SimpleAudioExperiment.xlsx',
  seed: undefined, name: 'trials'
});
psychoJS.experiment.addLoop(trials); // add the loop to the experiment
currentLoop = trials; // we're now the current loop

// Schedule all the trials in the trialList:
for (const thisTrial of trials) {
  snapshot = trials.getSnapshot();
  trialsLoopScheduler.add(importConditions(snapshot));
  trialsLoopScheduler.add(trialRoutineBegin(snapshot));
  trialsLoopScheduler.add(trialRoutineEachFrame());
  trialsLoopScheduler.add(trialRoutineEnd(snapshot));
  trialsLoopScheduler.add(trialsLoopEndIteration(trialsLoopScheduler, snapshot));
}

return Scheduler.Event.NEXT;

```

}  
}

async function trialsLoopEnd() {  
// terminate loop  
psychoJS.experiment.removeLoop(trials);  
// update the current loop from the ExperimentHandler  
if (psychoJS.experiment.\_unfinishedLoops.length\>0)  
currentLoop = psychoJS.experiment.\_unfinishedLoops.at(-1);  
else  
currentLoop = psychoJS.experiment; // so we use addData from the experiment  
return Scheduler.Event.NEXT;  
}

function trialsLoopEndIteration(scheduler, snapshot) {  
// ------Prepare for next entry------  
return async function () {  
if (typeof snapshot !== ‘undefined’) {  
// ------Check if user ended loop early------  
if (snapshot.finished) {  
// Check for and save orphaned data  
if (psychoJS.experiment.isEntryEmpty()) {  
psychoJS.experiment.nextEntry(snapshot);  
}  
scheduler.stop();  
} else {  
psychoJS.experiment.nextEntry(snapshot);  
}  
return Scheduler.Event.NEXT;  
}  
};  
}

var t;  
var frameN;  
var continueRoutine;  
var trialComponents;  
function trialRoutineBegin(snapshot) {  
return async function () {  
TrialHandler.fromSnapshot(snapshot); // ensure that .thisN vals are up to date

```
//--- Prepare to start Routine 'trial' ---
t = 0;
trialClock.reset(); // clock
frameN = -1;
continueRoutine = true; // until we're told otherwise
// update component parameters for each repeat
psychoJS.experiment.addData('trial.started', globalClock.getTime());
sound_1.setValue(SoundFile);
sound_1.setVolume(3.0);
// keep track of which components have finished
trialComponents = [];
trialComponents.push(sound_1);

for (const thisComponent of trialComponents)
  if ('status' in thisComponent)
    thisComponent.status = PsychoJS.Status.NOT_STARTED;
return Scheduler.Event.NEXT;

```

}  
}

function trialRoutineEachFrame() {  
return async function () {  
//— Loop for each frame of Routine ‘trial’ —  
// get current time  
t = trialClock.getTime();  
frameN = frameN + 1;// number of completed frames (so 0 is the first frame)  
// update/draw components on each frame  
// start/stop sound\_1  
if (t \>= 0.0 && sound\_1.status === PsychoJS.Status.NOT\_STARTED) {  
// keep track of start time/frame for later  
sound\_1.tStart = t; // (not accounting for frame time here)  
sound\_1.frameNStart = frameN; // exact frame index

```
  psychoJS.window.callOnFlip(function(){ sound_1.play(); }); // screen flip
  sound_1.status = PsychoJS.Status.STARTED;
}
if (t >= (sound_1.getDuration() + sound_1.tStart) && sound_1.status === PsychoJS.Status.STARTED) {
  sound_1.stop(); // stop the sound (if longer than duration)
  sound_1.status = PsychoJS.Status.FINISHED;
}
// check for quit (typically the Esc key)
if (psychoJS.experiment.experimentEnded || psychoJS.eventManager.getKeys({keyList:['escape']}).length > 0) {
  return quitPsychoJS('The [Escape] key was pressed. Goodbye!', false);
}

// check if the Routine should terminate
if (!continueRoutine) { // a component has requested a forced-end of Routine
  return Scheduler.Event.NEXT;
}

continueRoutine = false; // reverts to True if at least one component still running
for (const thisComponent of trialComponents)
  if ('status' in thisComponent && thisComponent.status !== PsychoJS.Status.FINISHED) {
    continueRoutine = true;
    break;
  }

// refresh the screen if continuing
if (continueRoutine) {
  return Scheduler.Event.FLIP_REPEAT;
} else {
  return Scheduler.Event.NEXT;
}

```

};  
}

function trialRoutineEnd(snapshot) {  
return async function () {  
//— Ending Routine ‘trial’ —  
for (const thisComponent of trialComponents) {  
if (typeof thisComponent.setAutoDraw === ‘function’) {  
thisComponent.setAutoDraw(false);  
}  
}  
psychoJS.experiment.addData(‘trial.stopped’, globalClock.getTime());  
sound\_1.stop(); // ensure sound has stopped at end of Routine  
// the Routine “trial” was not non-slip safe, so reset the non-slip timer  
routineTimer.reset();

```
// Routines running outside a loop should always advance the datafile row
if (currentLoop === psychoJS.experiment) {
  psychoJS.experiment.nextEntry(snapshot);
}
return Scheduler.Event.NEXT;

```

}  
}

function importConditions(currentLoop) {  
return async function () {  
psychoJS.importAttributes(currentLoop.getCurrentTrial());  
return Scheduler.Event.NEXT;  
};  
}

async function quitPsychoJS(message, isCompleted) {  
// Check for and save orphaned data  
if (psychoJS.experiment.isEntryEmpty()) {  
psychoJS.experiment.nextEntry();  
}  
psychoJS.window.close();  
psychoJS.quit({message: message, isCompleted: isCompleted});

return Scheduler.Event.QUIT;  
}

---

<div class="post-metadata">

### Author: ![VBaake](https://avatars.discourse-cdn.com/v4/letter/v/7ab992/32.png) [@VBaake](https://discourse.psychopy.org/u/VBaake)
#### Post date: [April 9, 2024, 6:22pm UTC](https://discourse.psychopy.org/t/pavlovia-only-plays-1st-audio-file-but-psychopy-locally-plays-all-audio/35935/2 "2024-04-09T18:22:09Z")

</div>

Hi, I’m currently having this same issue, I was wondering if you ever found a solution?

---

<div class="post-metadata">

### Author: ![wakecarter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.psychopy.org/wakecarter/32/5753_2.png) [@wakecarter](https://discourse.psychopy.org/u/wakecarter)
#### Post date: [April 10, 2024, 7:02am UTC](https://discourse.psychopy.org/t/pavlovia-only-plays-1st-audio-file-but-psychopy-locally-plays-all-audio/35935/3 "2024-04-10T07:02:18Z")

</div>

My standard response to this issue is to give the audio a start time of between.2 and .5 seconds to allow it to load.

---

<div class="post-metadata">

### Author: ![VBaake](https://avatars.discourse-cdn.com/v4/letter/v/7ab992/32.png) [@VBaake](https://discourse.psychopy.org/u/VBaake)
#### Post date: [April 11, 2024, 6:42pm UTC](https://discourse.psychopy.org/t/pavlovia-only-plays-1st-audio-file-but-psychopy-locally-plays-all-audio/35935/4 "2024-04-11T18:42:59Z")

</div>

Thank you so much, that did the trick!
