@jspsych/plugin-audio-keyboard-response 1.1.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,35 +1,49 @@
1
- import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych";
1
+ import { JsPsychPlugin, ParameterType, JsPsych, TrialType } from 'jspsych';
2
+
2
3
  declare const info: {
3
4
  readonly name: "audio-keyboard-response";
5
+ readonly version: string;
4
6
  readonly parameters: {
5
7
  /** The audio file to be played. */
6
8
  readonly stimulus: {
7
9
  readonly type: ParameterType.AUDIO;
8
- readonly pretty_name: "Stimulus";
9
10
  readonly default: any;
10
11
  };
11
- /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */
12
+ /** This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus.
13
+ * Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) -
14
+ * see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
15
+ * and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/)
16
+ * for more examples. Any key presses that are not listed in the array will be ignored. The default value of `"ALL_KEYS"`
17
+ * means that all keys will be accepted as valid responses. Specifying `"NO_KEYS"` will mean that no responses are allowed.
18
+ */
12
19
  readonly choices: {
13
20
  readonly type: ParameterType.KEYS;
14
- readonly pretty_name: "Choices";
15
21
  readonly default: "ALL_KEYS";
16
22
  };
17
- /** Any content here will be displayed below the stimulus. */
23
+ /** This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that
24
+ * it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press).
25
+ */
18
26
  readonly prompt: {
19
27
  readonly type: ParameterType.HTML_STRING;
20
28
  readonly pretty_name: "Prompt";
21
29
  readonly default: any;
22
30
  };
23
- /** The maximum duration to wait for a response. */
31
+ /** How long to wait for the participant to make a response before ending the trial in milliseconds. If the
32
+ * participant fails to make a response before this timer is reached, the participant's response will be
33
+ * recorded as null for the trial and the trial will end. If the value of this parameter is null, then the
34
+ * trial will wait for a response indefinitely.
35
+ */
24
36
  readonly trial_duration: {
25
37
  readonly type: ParameterType.INT;
26
- readonly pretty_name: "Trial duration";
27
38
  readonly default: any;
28
39
  };
29
- /** If true, the trial will end when user makes a response. */
40
+ /** If true, then the trial will end whenever the participant makes a response (assuming they make their
41
+ * response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will
42
+ * continue until the value for `trial_duration` is reached. You can use set this parameter to `false` to
43
+ * force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete
44
+ */
30
45
  readonly response_ends_trial: {
31
46
  readonly type: ParameterType.BOOL;
32
- readonly pretty_name: "Response ends trial";
33
47
  readonly default: true;
34
48
  };
35
49
  /** If true, then the trial will end as soon as the audio file finishes playing. */
@@ -38,56 +52,98 @@ declare const info: {
38
52
  readonly pretty_name: "Trial ends after audio";
39
53
  readonly default: false;
40
54
  };
41
- /** If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before a response is accepted. */
55
+ /** If true, then responses are allowed while the audio is playing. If false, then the audio must finish
56
+ * playing before a keyboard response is accepted. Once the audio has played all the way through, a valid
57
+ * keyboard response is allowed (including while the audio is being re-played via on-screen playback controls).
58
+ */
42
59
  readonly response_allowed_while_playing: {
43
60
  readonly type: ParameterType.BOOL;
44
- readonly pretty_name: "Response allowed while playing";
45
61
  readonly default: true;
46
62
  };
47
63
  };
64
+ readonly data: {
65
+ /** Indicates which key the participant pressed. If no key was pressed before the trial ended, then the value will be `null`. */
66
+ readonly response: {
67
+ readonly type: ParameterType.STRING;
68
+ };
69
+ /** The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus
70
+ * first began playing until the participant made a key response. If no key was pressed before the trial ended, then the
71
+ * value will be `null`.
72
+ */
73
+ readonly rt: {
74
+ readonly type: ParameterType.INT;
75
+ };
76
+ /** Path to the audio file that played during the trial. */
77
+ readonly stimulus: {
78
+ readonly type: ParameterType.STRING;
79
+ };
80
+ };
81
+ readonly citations: "__CITATIONS__";
48
82
  };
49
83
  type Info = typeof info;
50
84
  /**
51
- * **audio-keyboard-response**
85
+ * This plugin plays audio files and records responses generated with the keyboard.
86
+ *
87
+ * If the browser supports it, audio files are played using the WebAudio API. This allows for reasonably precise timing of the
88
+ * playback. The timing of responses generated is measured against the WebAudio specific clock, improving the measurement of
89
+ * response times. If the browser does not support the WebAudio API, then the audio file is played with HTML5 audio.
52
90
  *
53
- * jsPsych plugin for playing an audio file and getting a keyboard response
91
+ * Audio files can be automatically preloaded by jsPsych using the [`preload` plugin](preload.md). However, if you are using
92
+ * timeline variables or another dynamic method to specify the audio stimulus, then you will need to [manually preload](../overview/media-preloading.md#manual-preloading) the audio.
93
+ *
94
+ * The trial can end when the participant responds, when the audio file has finished playing, or if the participant has
95
+ * failed to respond within a fixed length of time. You can also prevent a keyboard response from being recorded before
96
+ * the audio has finished playing.
54
97
  *
55
98
  * @author Josh de Leeuw
56
- * @see {@link https://www.jspsych.org/plugins/jspsych-audio-keyboard-response/ audio-keyboard-response plugin documentation on jspsych.org}
99
+ * @see {@link https://www.jspsych.org/latest/plugins/audio-keyboard-response/ audio-keyboard-response plugin documentation on jspsych.org}
57
100
  */
58
101
  declare class AudioKeyboardResponsePlugin implements JsPsychPlugin<Info> {
59
102
  private jsPsych;
60
103
  static info: {
61
104
  readonly name: "audio-keyboard-response";
105
+ readonly version: string;
62
106
  readonly parameters: {
63
107
  /** The audio file to be played. */
64
108
  readonly stimulus: {
65
109
  readonly type: ParameterType.AUDIO;
66
- readonly pretty_name: "Stimulus";
67
110
  readonly default: any;
68
111
  };
69
- /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */
112
+ /** This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus.
113
+ * Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) -
114
+ * see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
115
+ * and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/)
116
+ * for more examples. Any key presses that are not listed in the array will be ignored. The default value of `"ALL_KEYS"`
117
+ * means that all keys will be accepted as valid responses. Specifying `"NO_KEYS"` will mean that no responses are allowed.
118
+ */
70
119
  readonly choices: {
71
120
  readonly type: ParameterType.KEYS;
72
- readonly pretty_name: "Choices";
73
121
  readonly default: "ALL_KEYS";
74
122
  };
75
- /** Any content here will be displayed below the stimulus. */
123
+ /** This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that
124
+ * it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press).
125
+ */
76
126
  readonly prompt: {
77
127
  readonly type: ParameterType.HTML_STRING;
78
128
  readonly pretty_name: "Prompt";
79
129
  readonly default: any;
80
130
  };
81
- /** The maximum duration to wait for a response. */
131
+ /** How long to wait for the participant to make a response before ending the trial in milliseconds. If the
132
+ * participant fails to make a response before this timer is reached, the participant's response will be
133
+ * recorded as null for the trial and the trial will end. If the value of this parameter is null, then the
134
+ * trial will wait for a response indefinitely.
135
+ */
82
136
  readonly trial_duration: {
83
137
  readonly type: ParameterType.INT;
84
- readonly pretty_name: "Trial duration";
85
138
  readonly default: any;
86
139
  };
87
- /** If true, the trial will end when user makes a response. */
140
+ /** If true, then the trial will end whenever the participant makes a response (assuming they make their
141
+ * response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will
142
+ * continue until the value for `trial_duration` is reached. You can use set this parameter to `false` to
143
+ * force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete
144
+ */
88
145
  readonly response_ends_trial: {
89
146
  readonly type: ParameterType.BOOL;
90
- readonly pretty_name: "Response ends trial";
91
147
  readonly default: true;
92
148
  };
93
149
  /** If true, then the trial will end as soon as the audio file finishes playing. */
@@ -96,20 +152,49 @@ declare class AudioKeyboardResponsePlugin implements JsPsychPlugin<Info> {
96
152
  readonly pretty_name: "Trial ends after audio";
97
153
  readonly default: false;
98
154
  };
99
- /** If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before a response is accepted. */
155
+ /** If true, then responses are allowed while the audio is playing. If false, then the audio must finish
156
+ * playing before a keyboard response is accepted. Once the audio has played all the way through, a valid
157
+ * keyboard response is allowed (including while the audio is being re-played via on-screen playback controls).
158
+ */
100
159
  readonly response_allowed_while_playing: {
101
160
  readonly type: ParameterType.BOOL;
102
- readonly pretty_name: "Response allowed while playing";
103
161
  readonly default: true;
104
162
  };
105
163
  };
164
+ readonly data: {
165
+ /** Indicates which key the participant pressed. If no key was pressed before the trial ended, then the value will be `null`. */
166
+ readonly response: {
167
+ readonly type: ParameterType.STRING;
168
+ };
169
+ /** The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus
170
+ * first began playing until the participant made a key response. If no key was pressed before the trial ended, then the
171
+ * value will be `null`.
172
+ */
173
+ readonly rt: {
174
+ readonly type: ParameterType.INT;
175
+ };
176
+ /** Path to the audio file that played during the trial. */
177
+ readonly stimulus: {
178
+ readonly type: ParameterType.STRING;
179
+ };
180
+ };
181
+ readonly citations: "__CITATIONS__";
106
182
  };
107
183
  private audio;
184
+ private params;
185
+ private display;
186
+ private response;
187
+ private startTime;
188
+ private finish;
108
189
  constructor(jsPsych: JsPsych);
109
190
  trial(display_element: HTMLElement, trial: TrialType<Info>, on_load: () => void): Promise<unknown>;
110
- simulate(trial: TrialType<Info>, simulation_mode: any, simulation_options: any, load_callback: () => void): void;
191
+ private end_trial;
192
+ private after_response;
193
+ private setup_keyboard_listener;
194
+ simulate(trial: TrialType<Info>, simulation_mode: any, simulation_options: any, load_callback: () => void): Promise<any>;
111
195
  private simulate_data_only;
112
196
  private simulate_visual;
113
197
  private create_simulation_data;
114
198
  }
115
- export default AudioKeyboardResponsePlugin;
199
+
200
+ export { AudioKeyboardResponsePlugin as default };
package/dist/index.js CHANGED
@@ -1,235 +1,211 @@
1
+ import autoBind from 'auto-bind';
1
2
  import { ParameterType } from 'jspsych';
2
3
 
4
+ var version = "2.1.0";
5
+
3
6
  const info = {
4
- name: "audio-keyboard-response",
5
- parameters: {
6
- /** The audio file to be played. */
7
- stimulus: {
8
- type: ParameterType.AUDIO,
9
- pretty_name: "Stimulus",
10
- default: undefined,
11
- },
12
- /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */
13
- choices: {
14
- type: ParameterType.KEYS,
15
- pretty_name: "Choices",
16
- default: "ALL_KEYS",
17
- },
18
- /** Any content here will be displayed below the stimulus. */
19
- prompt: {
20
- type: ParameterType.HTML_STRING,
21
- pretty_name: "Prompt",
22
- default: null,
23
- },
24
- /** The maximum duration to wait for a response. */
25
- trial_duration: {
26
- type: ParameterType.INT,
27
- pretty_name: "Trial duration",
28
- default: null,
29
- },
30
- /** If true, the trial will end when user makes a response. */
31
- response_ends_trial: {
32
- type: ParameterType.BOOL,
33
- pretty_name: "Response ends trial",
34
- default: true,
35
- },
36
- /** If true, then the trial will end as soon as the audio file finishes playing. */
37
- trial_ends_after_audio: {
38
- type: ParameterType.BOOL,
39
- pretty_name: "Trial ends after audio",
40
- default: false,
41
- },
42
- /** If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before a response is accepted. */
43
- response_allowed_while_playing: {
44
- type: ParameterType.BOOL,
45
- pretty_name: "Response allowed while playing",
46
- default: true,
47
- },
7
+ name: "audio-keyboard-response",
8
+ version,
9
+ parameters: {
10
+ /** The audio file to be played. */
11
+ stimulus: {
12
+ type: ParameterType.AUDIO,
13
+ default: void 0
48
14
  },
49
- };
50
- /**
51
- * **audio-keyboard-response**
52
- *
53
- * jsPsych plugin for playing an audio file and getting a keyboard response
54
- *
55
- * @author Josh de Leeuw
56
- * @see {@link https://www.jspsych.org/plugins/jspsych-audio-keyboard-response/ audio-keyboard-response plugin documentation on jspsych.org}
57
- */
58
- class AudioKeyboardResponsePlugin {
59
- constructor(jsPsych) {
60
- this.jsPsych = jsPsych;
15
+ /** This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus.
16
+ * Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) -
17
+ * see [this page](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
18
+ * and [this page (event.key column)](https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/)
19
+ * for more examples. Any key presses that are not listed in the array will be ignored. The default value of `"ALL_KEYS"`
20
+ * means that all keys will be accepted as valid responses. Specifying `"NO_KEYS"` will mean that no responses are allowed.
21
+ */
22
+ choices: {
23
+ type: ParameterType.KEYS,
24
+ default: "ALL_KEYS"
25
+ },
26
+ /** This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that
27
+ * it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press).
28
+ */
29
+ prompt: {
30
+ type: ParameterType.HTML_STRING,
31
+ pretty_name: "Prompt",
32
+ default: null
33
+ },
34
+ /** How long to wait for the participant to make a response before ending the trial in milliseconds. If the
35
+ * participant fails to make a response before this timer is reached, the participant's response will be
36
+ * recorded as null for the trial and the trial will end. If the value of this parameter is null, then the
37
+ * trial will wait for a response indefinitely.
38
+ */
39
+ trial_duration: {
40
+ type: ParameterType.INT,
41
+ default: null
42
+ },
43
+ /** If true, then the trial will end whenever the participant makes a response (assuming they make their
44
+ * response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will
45
+ * continue until the value for `trial_duration` is reached. You can use set this parameter to `false` to
46
+ * force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete
47
+ */
48
+ response_ends_trial: {
49
+ type: ParameterType.BOOL,
50
+ default: true
51
+ },
52
+ /** If true, then the trial will end as soon as the audio file finishes playing. */
53
+ trial_ends_after_audio: {
54
+ type: ParameterType.BOOL,
55
+ pretty_name: "Trial ends after audio",
56
+ default: false
57
+ },
58
+ /** If true, then responses are allowed while the audio is playing. If false, then the audio must finish
59
+ * playing before a keyboard response is accepted. Once the audio has played all the way through, a valid
60
+ * keyboard response is allowed (including while the audio is being re-played via on-screen playback controls).
61
+ */
62
+ response_allowed_while_playing: {
63
+ type: ParameterType.BOOL,
64
+ default: true
61
65
  }
62
- trial(display_element, trial, on_load) {
63
- // hold the .resolve() function from the Promise that ends the trial
64
- let trial_complete;
65
- // setup stimulus
66
- var context = this.jsPsych.pluginAPI.audioContext();
67
- // store response
68
- var response = {
69
- rt: null,
70
- key: null,
71
- };
72
- // record webaudio context start time
73
- var startTime;
74
- // load audio file
75
- this.jsPsych.pluginAPI
76
- .getAudioBuffer(trial.stimulus)
77
- .then((buffer) => {
78
- if (context !== null) {
79
- this.audio = context.createBufferSource();
80
- this.audio.buffer = buffer;
81
- this.audio.connect(context.destination);
82
- }
83
- else {
84
- this.audio = buffer;
85
- this.audio.currentTime = 0;
86
- }
87
- setupTrial();
88
- })
89
- .catch((err) => {
90
- console.error(`Failed to load audio file "${trial.stimulus}". Try checking the file path. We recommend using the preload plugin to load audio files.`);
91
- console.error(err);
92
- });
93
- const setupTrial = () => {
94
- // set up end event if trial needs it
95
- if (trial.trial_ends_after_audio) {
96
- this.audio.addEventListener("ended", end_trial);
97
- }
98
- // show prompt if there is one
99
- if (trial.prompt !== null) {
100
- display_element.innerHTML = trial.prompt;
101
- }
102
- // start audio
103
- if (context !== null) {
104
- startTime = context.currentTime;
105
- this.audio.start(startTime);
106
- }
107
- else {
108
- this.audio.play();
109
- }
110
- // start keyboard listener when trial starts or sound ends
111
- if (trial.response_allowed_while_playing) {
112
- setup_keyboard_listener();
113
- }
114
- else if (!trial.trial_ends_after_audio) {
115
- this.audio.addEventListener("ended", setup_keyboard_listener);
116
- }
117
- // end trial if time limit is set
118
- if (trial.trial_duration !== null) {
119
- this.jsPsych.pluginAPI.setTimeout(() => {
120
- end_trial();
121
- }, trial.trial_duration);
122
- }
123
- on_load();
124
- };
125
- // function to end trial when it is time
126
- const end_trial = () => {
127
- // kill any remaining setTimeout handlers
128
- this.jsPsych.pluginAPI.clearAllTimeouts();
129
- // stop the audio file if it is playing
130
- // remove end event listeners if they exist
131
- if (context !== null) {
132
- this.audio.stop();
133
- }
134
- else {
135
- this.audio.pause();
136
- }
137
- this.audio.removeEventListener("ended", end_trial);
138
- this.audio.removeEventListener("ended", setup_keyboard_listener);
139
- // kill keyboard listeners
140
- this.jsPsych.pluginAPI.cancelAllKeyboardResponses();
141
- // gather the data to store for the trial
142
- var trial_data = {
143
- rt: response.rt,
144
- stimulus: trial.stimulus,
145
- response: response.key,
146
- };
147
- // clear the display
148
- display_element.innerHTML = "";
149
- // move on to the next trial
150
- this.jsPsych.finishTrial(trial_data);
151
- trial_complete();
152
- };
153
- // function to handle responses by the subject
154
- function after_response(info) {
155
- // only record the first response
156
- if (response.key == null) {
157
- response = info;
158
- }
159
- if (trial.response_ends_trial) {
160
- end_trial();
161
- }
162
- }
163
- const setup_keyboard_listener = () => {
164
- // start the response listener
165
- if (context !== null) {
166
- this.jsPsych.pluginAPI.getKeyboardResponse({
167
- callback_function: after_response,
168
- valid_responses: trial.choices,
169
- rt_method: "audio",
170
- persist: false,
171
- allow_held_key: false,
172
- audio_context: context,
173
- audio_context_start_time: startTime,
174
- });
175
- }
176
- else {
177
- this.jsPsych.pluginAPI.getKeyboardResponse({
178
- callback_function: after_response,
179
- valid_responses: trial.choices,
180
- rt_method: "performance",
181
- persist: false,
182
- allow_held_key: false,
183
- });
184
- }
185
- };
186
- return new Promise((resolve) => {
187
- trial_complete = resolve;
188
- });
66
+ },
67
+ data: {
68
+ /** Indicates which key the participant pressed. If no key was pressed before the trial ended, then the value will be `null`. */
69
+ response: {
70
+ type: ParameterType.STRING
71
+ },
72
+ /** The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus
73
+ * first began playing until the participant made a key response. If no key was pressed before the trial ended, then the
74
+ * value will be `null`.
75
+ */
76
+ rt: {
77
+ type: ParameterType.INT
78
+ },
79
+ /** Path to the audio file that played during the trial. */
80
+ stimulus: {
81
+ type: ParameterType.STRING
189
82
  }
190
- simulate(trial, simulation_mode, simulation_options, load_callback) {
191
- if (simulation_mode == "data-only") {
192
- load_callback();
193
- this.simulate_data_only(trial, simulation_options);
194
- }
195
- if (simulation_mode == "visual") {
196
- this.simulate_visual(trial, simulation_options, load_callback);
197
- }
83
+ },
84
+ // prettier-ignore
85
+ citations: {
86
+ "apa": "de Leeuw, J. R., Gilbert, R. A., & Luchterhandt, B. (2023). jsPsych: Enabling an Open-Source Collaborative Ecosystem of Behavioral Experiments. Journal of Open Source Software, 8(85), 5351. https://doi.org/10.21105/joss.05351 ",
87
+ "bibtex": '@article{Leeuw2023jsPsych, author = {de Leeuw, Joshua R. and Gilbert, Rebecca A. and Luchterhandt, Bj{\\" o}rn}, journal = {Journal of Open Source Software}, doi = {10.21105/joss.05351}, issn = {2475-9066}, number = {85}, year = {2023}, month = {may 11}, pages = {5351}, publisher = {Open Journals}, title = {jsPsych: Enabling an {Open}-{Source} {Collaborative} {Ecosystem} of {Behavioral} {Experiments}}, url = {https://joss.theoj.org/papers/10.21105/joss.05351}, volume = {8}, } '
88
+ }
89
+ };
90
+ class AudioKeyboardResponsePlugin {
91
+ constructor(jsPsych) {
92
+ this.jsPsych = jsPsych;
93
+ this.response = { rt: null, key: null };
94
+ autoBind(this);
95
+ }
96
+ static {
97
+ this.info = info;
98
+ }
99
+ trial(display_element, trial, on_load) {
100
+ return new Promise(async (resolve) => {
101
+ this.finish = resolve;
102
+ this.params = trial;
103
+ this.display = display_element;
104
+ this.audio = await this.jsPsych.pluginAPI.getAudioPlayer(trial.stimulus);
105
+ if (trial.trial_ends_after_audio) {
106
+ this.audio.addEventListener("ended", this.end_trial);
107
+ }
108
+ if (trial.prompt !== null) {
109
+ display_element.innerHTML = trial.prompt;
110
+ }
111
+ this.startTime = this.jsPsych.pluginAPI.audioContext()?.currentTime;
112
+ if (trial.response_allowed_while_playing) {
113
+ this.setup_keyboard_listener();
114
+ } else if (!trial.trial_ends_after_audio) {
115
+ this.audio.addEventListener("ended", this.setup_keyboard_listener);
116
+ }
117
+ if (trial.trial_duration !== null) {
118
+ this.jsPsych.pluginAPI.setTimeout(() => {
119
+ this.end_trial();
120
+ }, trial.trial_duration);
121
+ }
122
+ on_load();
123
+ this.audio.play();
124
+ });
125
+ }
126
+ end_trial() {
127
+ this.jsPsych.pluginAPI.clearAllTimeouts();
128
+ this.audio.stop();
129
+ this.audio.removeEventListener("ended", this.end_trial);
130
+ this.audio.removeEventListener("ended", this.setup_keyboard_listener);
131
+ this.jsPsych.pluginAPI.cancelAllKeyboardResponses();
132
+ var trial_data = {
133
+ rt: this.response.rt,
134
+ response: this.response.key,
135
+ stimulus: this.params.stimulus
136
+ };
137
+ this.display.innerHTML = "";
138
+ this.finish(trial_data);
139
+ }
140
+ after_response(info2) {
141
+ this.response = info2;
142
+ if (this.params.response_ends_trial) {
143
+ this.end_trial();
198
144
  }
199
- simulate_data_only(trial, simulation_options) {
200
- const data = this.create_simulation_data(trial, simulation_options);
201
- this.jsPsych.finishTrial(data);
145
+ }
146
+ setup_keyboard_listener() {
147
+ if (this.jsPsych.pluginAPI.useWebaudio) {
148
+ this.jsPsych.pluginAPI.getKeyboardResponse({
149
+ callback_function: this.after_response,
150
+ valid_responses: this.params.choices,
151
+ rt_method: "audio",
152
+ persist: false,
153
+ allow_held_key: false,
154
+ audio_context: this.jsPsych.pluginAPI.audioContext(),
155
+ audio_context_start_time: this.startTime
156
+ });
157
+ } else {
158
+ this.jsPsych.pluginAPI.getKeyboardResponse({
159
+ callback_function: this.after_response,
160
+ valid_responses: this.params.choices,
161
+ rt_method: "performance",
162
+ persist: false,
163
+ allow_held_key: false
164
+ });
202
165
  }
203
- simulate_visual(trial, simulation_options, load_callback) {
204
- const data = this.create_simulation_data(trial, simulation_options);
205
- const display_element = this.jsPsych.getDisplayElement();
206
- const respond = () => {
207
- if (data.rt !== null) {
208
- this.jsPsych.pluginAPI.pressKey(data.response, data.rt);
209
- }
210
- };
211
- this.trial(display_element, trial, () => {
212
- load_callback();
213
- if (!trial.response_allowed_while_playing) {
214
- this.audio.addEventListener("ended", respond);
215
- }
216
- else {
217
- respond();
218
- }
219
- });
166
+ }
167
+ async simulate(trial, simulation_mode, simulation_options, load_callback) {
168
+ if (simulation_mode == "data-only") {
169
+ load_callback();
170
+ return this.simulate_data_only(trial, simulation_options);
220
171
  }
221
- create_simulation_data(trial, simulation_options) {
222
- const default_data = {
223
- stimulus: trial.stimulus,
224
- rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),
225
- response: this.jsPsych.pluginAPI.getValidKey(trial.choices),
226
- };
227
- const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);
228
- this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);
229
- return data;
172
+ if (simulation_mode == "visual") {
173
+ return this.simulate_visual(trial, simulation_options, load_callback);
230
174
  }
175
+ }
176
+ simulate_data_only(trial, simulation_options) {
177
+ const data = this.create_simulation_data(trial, simulation_options);
178
+ return data;
179
+ }
180
+ async simulate_visual(trial, simulation_options, load_callback) {
181
+ const data = this.create_simulation_data(trial, simulation_options);
182
+ const display_element = this.jsPsych.getDisplayElement();
183
+ const respond = () => {
184
+ if (data.rt !== null) {
185
+ this.jsPsych.pluginAPI.pressKey(data.response, data.rt);
186
+ }
187
+ };
188
+ const result = await this.trial(display_element, trial, () => {
189
+ load_callback();
190
+ if (!trial.response_allowed_while_playing) {
191
+ this.audio.addEventListener("ended", respond);
192
+ } else {
193
+ respond();
194
+ }
195
+ });
196
+ return result;
197
+ }
198
+ create_simulation_data(trial, simulation_options) {
199
+ const default_data = {
200
+ stimulus: trial.stimulus,
201
+ rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),
202
+ response: this.jsPsych.pluginAPI.getValidKey(trial.choices)
203
+ };
204
+ const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);
205
+ this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);
206
+ return data;
207
+ }
231
208
  }
232
- AudioKeyboardResponsePlugin.info = info;
233
209
 
234
210
  export { AudioKeyboardResponsePlugin as default };
235
211
  //# sourceMappingURL=index.js.map