Skip to content

Commit

Permalink
add docs, allow for shuffling of stimuli
Browse files Browse the repository at this point in the history
  • Loading branch information
jadeddelta committed Nov 12, 2024
1 parent 304ce22 commit 3a50f61
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 14 deletions.
36 changes: 30 additions & 6 deletions packages/plugin-headphone-check/docs/headphone-check.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,35 @@ Allows for one to check if a participant is wearing headphones using an auditory

In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.

| Parameter | Type | Default Value | Description |
| ------------------- | ---------------- | ------------------ | ---------------------------------------- |
| | | | |
| Parameter | Type | Default Value | Description |
| --------- | ------- | ------------------ | ------------------ |
| stimuli | array of audio files | *undefined* | The list of tones that will be played. |
| correct | array of integers | *undefined* | The list of correct answers, corresponding to each tone. Each number in the array is between 1-3, corresponding to the first, second, and third being the correct response. |
| total_trials | integer | 6 | Number of trials that will be played. |
| threshold | integer | 5 | Threshold of correct trials needed to pass the headphone screening. |
| trials_per_page | integer | 3 | Number of trials that are rendered on a single page. Must be a factor of `total_trials` so each page gets their own equal set of trials. |
| prompt | HTML string | `"<p>Listen to the following sounds and select which option is quietest. <br> Click the play button to listen to the sound, and select the correct option. <br> Test sounds can only be played once!</p>"` | An HTML-formatted string presented to the participant above the audio questions. |
| labels | array of strings | `["FIRST sound is SOFTEST", "SECOND sound is SOFTEST", "THIRD sound is SOFTEST"]` | A 3 element array containing the labels of the three radio buttons. |
| play_button_label | string | `"Play"` | The label of the play button. Will be used for calibration as well if enabled. |
| continue_button_label | string | `"Continue"` | The label of the continue button. Will be used for calibration as well if enabled. |
| sequential | boolean | `false` | If true, each stimulus must be played and completed from first to last. |
| shuffle | boolean | `true` | If true, the trials will be shuffled before being displayed to the participant. |
| sample_with_replacement | boolean | `false` | If true, on shuffle, the trials will be shuffled with replacement, meaning some trials may contain duplicates. |
| calibration | boolean | `true` | If true, a calibration sound will be played to allow the participant to adjust their volume. |
| calibration_stimulus | audio file | `null` | The audio file that will be played for calibration. |
| calibration_prompt | function | ``function (calibration_counter: number) { return `<p>Calibrating Volume: Press the play button below to play a sound. <br> Adjust the volume of the sound to a comfortable level, and click continue when you are ready. <br> You have ${calibration_counter} calibration attempts remaining.</p>`;}`` | A function taking in the current amount of calibration attempts, which acts to present this info along with a stimulus to the participant above the calibration button. |
| calibration_attempts | integer | 3 | The amount of times the user may play the calibration sound. |


## Data Generated

In addition to the [default data collected by all plugins](https://jspsych.org/latest/overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial.

| Name | Type | Value |
| --------- | ------- | ---------------------------------------- |
| | | |
| did_pass | boolean | If the participant passed the headphone screen. |
| total_correct | integer | Total number of correct responses. |
| responses | array of objects | An array of objects indicating what the headphone check stimulus was, which option the participant selected, and if it was correct. Has three fields: `stimulus`: Filepath of the stimulus object. `response`: The option the participant selected, from 1-3. `correct`: If the participant's response was correct. |

## Install

Expand Down Expand Up @@ -44,10 +62,16 @@ import HeadphoneCheck from '@jspsych-contrib/plugin-headphone-check';

## Examples

### Title of Example
### Basic Headphone Check
This example mimics the default configurations in the [original Headphone Check](https://github.com/mcdermottLab/HeadphoneCheck) plugin.

```javascript
var trial = {
type: jsPsychHeadphoneCheck
type: jsPsychHeadphoneCheck,
stimuli: ["./audio/antiphase_HC_ISO.wav", "./audio/antiphase_HC_IOS.wav", "./audio/antiphase_HC_SOI.wav", "./audio/antiphase_HC_SIO.wav", "./audio/antiphase_HC_OSI.wav", "./audio/antiphase_HC_OIS.wav"],
correct: [2, 3, 1, 1, 2, 3],
calibration_stimulus: "./audio/noise_calib_stim.wav",
sample_with_replacement: true,
sequential: true,
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
type: jsPsychHeadphoneCheck,
stimuli: ["./audio/antiphase_HC_ISO.wav", "./audio/antiphase_HC_IOS.wav", "./audio/antiphase_HC_SOI.wav", "./audio/antiphase_HC_SIO.wav", "./audio/antiphase_HC_OSI.wav", "./audio/antiphase_HC_OIS.wav"],
correct: [2, 3, 1, 1, 2, 3],
calibration: true,
calibration_stimulus: "./audio/noise_calib_stim.wav",
sequential: true,
shuffle: false,
};

jsPsych.run([preload, trial])
Expand Down
55 changes: 48 additions & 7 deletions packages/plugin-headphone-check/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const info = <const>{
array: true,
},
/** The list of correct answers, corresponding to each tone. Each number in the array is between 1-3,
* corresponding to the first, second, and third being correct or not. */
* corresponding to the first, second, and third being the correct response. */
correct: {
type: ParameterType.INT,
default: undefined,
Expand Down Expand Up @@ -58,11 +58,26 @@ const info = <const>{
type: ParameterType.STRING,
default: "Continue",
},
/** If a calibration sound will be played to allow the participant to adjust their volume. */
calibration: {
/** If true, each stimulus must be played and completed from first to last. */
sequential: {
type: ParameterType.BOOL,
default: false,
},
/** If true, the trials will be shuffled before being displayed to the participant. */
shuffle: {
type: ParameterType.BOOL,
default: true,
},
/** If true, on shuffle, the trials will be shuffled with replacement, meaning some trials may contain duplicates. */
sample_with_replacement: {
type: ParameterType.BOOL,
default: false,
},
/** If true, a calibration sound will be played to allow the participant to adjust their volume. */
calibration: {
type: ParameterType.BOOL,
default: true,
},
/** The audio file that will be played for calibration. */
calibration_stimulus: {
type: ParameterType.AUDIO,
Expand All @@ -76,7 +91,7 @@ const info = <const>{
return `<p>Calibrating Volume: Press the play button below to play a sound. <br> Adjust the volume of the sound to a comfortable level, and click continue when you are ready. <br> You have ${calibration_counter} calibration attempts remaining.</p>`;
},
},
/** The amount of times the user may play the calibraiton sound. */
/** The amount of times the user may play the calibration sound. */
calibration_attempts: {
type: ParameterType.INT,
default: 3,
Expand Down Expand Up @@ -149,6 +164,8 @@ class HeadphoneCheckPlugin implements JsPsychPlugin<Info> {
alreadyPlayed: boolean;
}[];
private trialContinueButton: HTMLButtonElement;
private stimuliList: string[];
private correctList: number[];

private currentPage: number;

Expand All @@ -170,6 +187,8 @@ class HeadphoneCheckPlugin implements JsPsychPlugin<Info> {
this.container = display_element;
this.container.innerHTML = this.css;
this.trialResources = [];
this.stimuliList = trial.stimuli;
this.correctList = trial.correct;
this.trialData = {
did_pass: null,
total_correct: 0,
Expand Down Expand Up @@ -225,8 +244,30 @@ class HeadphoneCheckPlugin implements JsPsychPlugin<Info> {
"Error from HeadphoneCheckPlugin: Calibration is enabled, but no calibration stimulus was provided."
);

// shuffle stimuli
this.stimuliList = this.params.stimuli;
this.correctList = this.params.correct;
if (this.params.shuffle) {
if (this.params.sample_with_replacement) {
this.stimuliList = this.jsPsych.randomization.sampleWithReplacement(
this.stimuliList,
this.params.total_trials
);
this.correctList = this.jsPsych.randomization.sampleWithReplacement(
this.correctList,
this.params.total_trials
);
} else {
var shuffled = this.jsPsych.randomization.shuffle([
...Array(this.params.total_trials).keys(),
]);
this.stimuliList = shuffled.map((i) => this.params.stimuli[i]);
this.correctList = shuffled.map((i) => this.params.correct[i]);
}
}

// instantiate trial resources
for (const [stimuliIndex, stimuli] of this.params.stimuli.entries()) {
for (const [stimuliIndex, stimuli] of this.stimuliList.entries()) {
var fieldset = document.createElement("fieldset");
fieldset.id = `jspsych-headphone-check-fieldset-${stimuliIndex}`;
fieldset.className = "jspsych-headphone-check-fieldset";
Expand Down Expand Up @@ -444,11 +485,11 @@ class HeadphoneCheckPlugin implements JsPsychPlugin<Info> {
var selected = Array.from(radioButtons).find((radio) => (radio as HTMLInputElement).checked);
if (selected) {
var selectedValue = parseInt((selected as HTMLInputElement).value);
var correctValue = this.params.correct[absoluteIndex] - 1;
var correctValue = this.correctList[absoluteIndex] - 1;
var correct = selectedValue === correctValue;
this.trialData.total_correct += correct ? 1 : 0;
this.trialData.responses.push({
stimulus: this.params.stimuli[absoluteIndex],
stimulus: this.stimuliList[absoluteIndex],
response: selectedValue + 1,
correct: correct,
});
Expand Down

0 comments on commit 3a50f61

Please sign in to comment.