OSCR

Timing-induced illusory percepts of pitch.

Code ↔ Paper

14 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 14 matches
  1. [1] § Experiment 1 › Methods › Materials ↔ E1/preparation/Tone_Generation (IP).ipynb, lines 40–67 · score 0.89 · sine waves, linear fade, linear rise, fundamental frequency, envelope, exponential
  2. [2] § Experiment 1 › Methods › Materials ↔ E2/preparation/Tone Generation (IP-AD).ipynb, lines 25–52 · score 0.89 · sine waves, linear fade, linear rise, fundamental frequency, envelope, exponential
  3. [3] § Experiment 1 › Results › Reaction time ↔ E1/analysis/Stats (IP).R, lines 111–191 · score 0.78 · bias opposing responses, bias conforming responses, bias neutral, reaction, interaction, pitch shift
  4. [4] § Experiment 1 › Results › Reaction time ↔ E1/analysis/Stats (IP).R, lines 111–191 · score 0.73 · bias conforming responses, bias neutral, bias opposing, confidence intervals, Reaction, Error
  5. [5] § Experiment 2 › Methods › Procedure ↔ E2/experiment_ip_adaptive.py, lines 182–206 · score 0.71 · interleaved staircase procedure, difficulty calibration, reversals, JND, shift
  6. [6] § Experiment 2 › Methods › Procedure ↔ E2/experiment_ip_adaptive.py, lines 131–143 · score 0.69 · fully randomized, shift direction, standard tone, preceded, blocks, probe tones
  7. [7] § Experiment 1 › Methods › Procedure ↔ E2/experiment_ip_adaptive.py, lines 131–143 · score 0.63 · shift direction, standard tones, Hz, preceded, repetition, randomized
  8. [8] § General discussion › Difficulty and perceptual sensitivity ↔ E2/analysis/Cue Integration.ipynb, lines 36–91 · score 0.60 · cue integration, spectral cue, temporal cues, Turquoise, pitch change, JND
  9. [9] § Experiment 1 › Results › Sensitivity & bias ↔ E2/analysis/Processing (IP-AD).ipynb, lines 52–147 · score 0.56 · alarm rates, hit rates, responded, pitch shift, octave, offset
  10. [10] § Experiment 1 › Results › Sensitivity & bias ↔ E1/analysis/Processing (IP).ipynb, lines 55–96 · score 0.53 · alarm rates, hit rates, responded, octave, offset
  11. [11] § Experiment 1 › Methods › Data analysis ↔ E2/analysis/Processing (IP-AD).ipynb, lines 52–147 · score 0.53 · alarm rates, hit rates, octave, scoring, offset, bias
  12. [12] § Experiment 1 › Results › Reaction time ↔ E1/analysis/Analysis (IP).ipynb, lines 221–257 · score 0.52 · Error bars, bias conforming, neutral, Reaction, opposing
  13. [13] § General discussion › Difficulty and perceptual sensitivity ↔ E2/analysis/Cue Integration.ipynb, lines 36–91 · score 0.51 · cue integration, turquoise, probability, pitch shift, spectral, JND
  14. [14] § Experiment 1 › Results › Reaction time ↔ E1/analysis/Analysis (IP).ipynb, lines 221–257 · score 0.51 · bias conforming, neutral, reaction, opposing, slower, pitch shift

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 381 lines · 15 KB · CC-BY-4.0 · 3 matches

  1. import json
  2. import itertools
  3. import os
  4. import random
  5. import librosa as lba
  6. import numpy as np
  7. import soundfile as sf
  8. from psychopy import constants, core, data, event, gui, logging, prefs, sound, visual
  9. prefs.general['units'] = 'pix'
  10. prefs.general['fullscr'] = False
  11. prefs.general['allowGUI'] = True
  12. def generate_percussive_tone(freq, duration, rise_duration, perc_duration, fade_duration, sr=44100):
  13. rise_length = int(rise_duration * sr / 1000)
  14. perc_length = int(perc_duration * sr / 1000)
  15. fade_length = int(fade_duration * sr / 1000)
  16. # Generate fundamental frequency (co)sine wave
  17. tone = lba.tone(freq, sr=sr, duration=duration / 1000)
  18. # Add first three harmonics (up to 2 octaves above) with slope of -3 db/half amplitude per octave
  19. for i in range(3):
  20. phase = random.random() * 2 * np.pi
  21. tone += lba.tone(freq * (i + 2), sr=sr, duration=duration / 1000, phi=phase) / (i + 2)
  22. # Apply exponential fade to create percussive envelope
  23. tone[-perc_length:] *= np.geomspace(1, .01, perc_length)
  24. # Apply short linear fade to ending so that amplitude fades to 0
  25. tone[-fade_length:] *= np.linspace(1, 0, fade_length)
  26. # Apply sharp linear rise to start of tone
  27. tone[:rise_length] *= np.linspace(0, 1, rise_length)
  28. # Rescale waveform to range [-1, 1]
  29. tone /= np.abs(tone).max()
  30. return tone
  31. def generate_sequences(base_freq, tone_name, base_shift, difficulties, ioi, offsets,
  32. base_intervals=5, mod_intervals=1, sr=44100,
  33. tone_dir='stimuli/tones/', out_dir='stimuli/'):
  34. if not os.path.exists(out_dir):
  35. os.mkdir(out_dir)
  36. ntones = base_intervals + mod_intervals + 1
  37. # Load standard tone
  38. base_tone, _ = lba.load(tone_dir + 'tone%s.wav' % tone_name, sr=sr)
  39. # Calculate frequencies of probe tones based on JND
  40. tones = dict()
  41. for d in difficulties:
  42. tones['%s-%s' % (tone_name, d)] = base_freq / 2 ** (base_shift * d / 1200)
  43. tones['%s+%s' % (tone_name, d)] = base_freq * 2 ** (base_shift * d / 1200)
  44. for pitch in tones:
  45. freq = tones[pitch]
  46. tone = generate_percussive_tone(freq, duration=250, rise_duration=10, perc_duration=240, fade_duration=10)
  47. for offset in offsets:
  48. # Create array of appropriate length to hold audio sequence
  49. ms_ioi = offset / 1000 # Millisecond interval preceding probe tone
  50. sequence = np.zeros(int(np.ceil(ntones * max(ioi / 1000, ms_ioi) * sr)), dtype=np.float32)
  51. # Insert tones at appropriate locations
  52. for i in range(ntones):
  53. # First several tones are spaced by the base IOI
  54. if i <= base_intervals:
  55. start = i * ioi / 1000 * sr
  56. start = int(np.ceil(start))
  57. # Place a copy of the tone in the proper location
  58. base_tone_end = start + base_tone.shape[0]
  59. sequence[start:base_tone_end] = base_tone
  60. # Final tone(s) is/are preceded by the modified IOI
  61. else:
  62. start = sr * ((base_intervals * ioi / 1000) + ((i - base_intervals) * ms_ioi))
  63. start = int(np.ceil(start))
  64. # Add pitch-shifted tone after the standard tones
  65. tone_end = start + tone.shape[0]
  66. sequence[start:tone_end] = tone
  67. # Cut silence from the end of the sequence
  68. sequence = np.trim_zeros(sequence, 'b')
  69. # Save sequences to WAV file
  70. sf.write(out_dir + 'sequence_%s_%i.wav' % (pitch, offset), sequence, sr)
  71. # Log information about the tones generated
  72. tones['base_shift_cents'] = base_shift
  73. tones['difficulties'] = difficulties
  74. with open(out_dir + 'tone_log.json', 'w') as f:
  75. json.dump(tones, f)
  76. ###
  77. # INITIALIZATION
  78. ###
  79. # VERSION NUMBERS
  80. # 1.0 - Difficulty levels of JND vs. 3/2 * JND
  81. # 1.1 - Increased difficulty to 1/2 JND vs. JND
  82. # Set constants
  83. # Experiment settings
  84. experiment_name = 'IPAD' # Experiment name
  85. version_num = '1.1' # Experiment version number (see above)
  86. frame_rate = 60 # Set monitor frame rate
  87. # Staircase settings
  88. min_shift = 0 # Minimum pitch shift in cents during staircase
  89. start_shift_small = 1 # The initial pitch shift in cents to use on small-start staircases
  90. start_shift_large = 25 # The initial pitch shift in cents to use on large-start staircases
  91. max_shift = 100 # Maximum pitch shift in cents during staircase
  92. n_up = 1 # Number of incorrect responses required to get easier
  93. n_down = 2 # Number of correct responses required to get harder
  94. reversals_per_staircase = 8 # The total number of reversals each staircase should be run for
  95. reversals_to_use = 4 # The last N reversals will be averaged to estimate the JND; even numbers reduce estimation bias
  96. step_sizes = [8, 8, 4, 4, 2, 2, 1, 1] # The step sizes for the staircase; can change after each reversal
  97. # Main task settings
  98. pretrial_delay = 1.5 # Seconds of pause before each trial
  99. standard_freq = 440 # Frequency of the standard tone (in Hz)
  100. tone_name = 'A4' # Name of the standard tone
  101. standard_ioi = 500 # Standard inter-onset interval (in ms)
  102. shifts = ['+', '-'] # Pitch directions
  103. intervals = [425, 500, 575] # Length of the interval preceding the probe tone
  104. difficulties = [.5, 1] # Pitch between high and low probes (in multiples of the JND)
  105. repetitions_per_block = 5 # Repetitions of each condition within each block (fully randomized)
  106. blocks = 4 # Number of blocks to run
  107. n_practice_trials_per_shift = 2 # Number of practice trials per shift direction
  108. practice_interval = standard_ioi # Interval preceding probe on practice trials
  109. practice_difficulty = 4 # Difference between high and low probes on practice trials (in multiples of the JND)
  110. # Randomize trial order
  111. # Practice trials include 2 up and 2 down shifts at the expected onset time and easy difficulty
  112. # Main trials include 4 blocks with 5 repetitions of each condition (2 shifts x 3 intervals x 2 difficulties) per block
  113. conditions = [c for c in itertools.product(shifts, intervals, difficulties)]
  114. trials_per_block = len(conditions) * repetitions_per_block # Number of trials per block
  115. trial_order = []
  116. for i in range(n_practice_trials_per_shift):
  117. for shift in shifts:
  118. trial_order.append({'shift': shift, 'interval': practice_interval, 'difficulty': practice_difficulty, 'event': 'practice'})
  119. random.shuffle(trial_order) # Shuffle practice trials
  120. for block in range(blocks):
  121. block_trials = conditions * repetitions_per_block
  122. random.shuffle(block_trials)
  123. for trial in block_trials:
  124. trial_order.append({'shift': trial[0], 'interval': trial[1], 'difficulty': trial[2], 'event': 'trial'})
  125. # Set up session info and open dialogue box to enter participant ID
  126. info_dict = dict(subject='', experimenter='')
  127. dlg = gui.DlgFromDict(dictionary=info_dict, sortKeys=False, title=experiment_name)
  128. if not dlg.OK:
  129. core.quit()
  130. info_dict['experiment'] = experiment_name
  131. info_dict['version'] = version_num
  132. # Set logging
  133. log = logging.LogFile('logs/%s_%s.log' % (experiment_name, info_dict['subject']), level=logging.EXP)
  134. logging.console.setLevel(logging.EXP)
  135. # Set up experiment, window, and text object
  136. win = visual.Window([1920, 1080], screen=0, monitor=None, color=(-1, -1, -1), fullscr=True)
  137. text = visual.TextStim(win, '', font='Arial', color=(1, 1, 1), height=72)
  138. exp = data.ExperimentHandler(name=experiment_name, version=version_num,
  139. extraInfo=info_dict,
  140. dataFileName='data/%s_%s_bkp' % (experiment_name, info_dict['subject']),
  141. savePickle=False, saveWideText=True,
  142. autoLog=True, appendFiles=False)
  143. # Set up interleaved staircase procedure used for difficulty calibration
  144. stair_conditions = [
  145. # Staircase testing JND for pitch increases starting from large shift
  146. {
  147. 'label': 'l+', 'startVal': start_shift_large, 'nReversals': reversals_per_staircase, 'stepSizes': step_sizes,
  148. 'nUp': n_up, 'nDown': n_down, 'minVal': min_shift, 'maxVal': max_shift, 'stepType': 'lin', 'shift': '+'
  149. },
  150. # Staircase testing JND for pitch increases starting from small shift
  151. {
  152. 'label': 's+', 'startVal': start_shift_small, 'nReversals': reversals_per_staircase, 'stepSizes': step_sizes,
  153. 'nUp': n_up, 'nDown': n_down, 'minVal': min_shift, 'maxVal': max_shift, 'stepType': 'lin', 'shift': '+'
  154. },
  155. # Staircase testing JND for pitch decreases starting from large shift
  156. {
  157. 'label': 'l-', 'startVal': start_shift_large, 'nReversals': reversals_per_staircase, 'stepSizes': step_sizes,
  158. 'nUp': n_up, 'nDown': n_down, 'minVal': min_shift, 'maxVal': max_shift, 'stepType': 'lin', 'shift': '-'
  159. },
  160. # Staircase testing JND for pitch decreases starting from small shift
  161. {
  162. 'label': 's-', 'startVal': start_shift_small, 'nReversals': reversals_per_staircase, 'stepSizes': step_sizes,
  163. 'nUp': n_up, 'nDown': n_down, 'minVal': min_shift, 'maxVal': max_shift, 'stepType': 'lin', 'shift': '-'
  164. }
  165. ]
  166. adaptive_stairs = data.MultiStairHandler(stairType='simple', method='random', conditions=stair_conditions, nTrials=1)
  167. exp.addLoop(adaptive_stairs)
  168. # Set up main task
  169. trials = data.TrialHandler(trial_order, 1, method='sequential',
  170. dataTypes=['event', 'shift', 'interval', 'difficulty',
  171. 'response', 'rt', 'jnd', 'full_jnd', 'correct'])
  172. exp.addLoop(trials)
  173. ###
  174. # ADAPTIVE DIFFICULTY TEST
  175. ###
  176. # Set up for loudness calibration
  177. standard_tone = sound.Sound('stimuli/tones/tone%s.wav' % tone_name)
  178. text.setText('Which was higher?')
  179. text.draw()
  180. win.flip()
  181. event.waitKeys(keyList=['space'], clearEvents=True)
  182. for intensity, condition in adaptive_stairs:
  183. # Pre-trial delay; load tones and randomize order while waiting
  184. win.flip()
  185. pretime = core.StaticPeriod(screenHz=frame_rate, win=win)
  186. pretime.start(pretrial_delay)
  187. shift = condition['shift']
  188. if intensity == 0:
  189. probe_tone = sound.Sound('stimuli/tones/tone%s.wav' % tone_name)
  190. else:
  191. probe_tone = sound.Sound('stimuli/tones/tone%s%s%d.wav' % (tone_name, shift, intensity))
  192. pretime.complete()
  193. # Stimulus presentation
  194. standard_tone.play()
  195. core.wait(0.5)
  196. probe_tone.play()
  197. # Ask for participant response
  198. text.setText('Which was higher?')
  199. text.draw()
  200. win.flip()
  201. response = event.waitKeys(keyList=['1', '2'], clearEvents=True)
  202. # Score correctness, and automatically reverse direction if we reach 0 intensity
  203. if intensity == 0:
  204. correctness = False
  205. else:
  206. correctness = ('2' in response and shift == '+') or ('1' in response and shift == '-')
  207. adaptive_stairs.addResponse(correctness)
  208. exp.nextEntry()
  209. # Set the JND to the average across the final N reversals of all staircases
  210. text.setText('Thinking...')
  211. text.draw()
  212. win.flip()
  213. reversals = []
  214. for staircase in adaptive_stairs.staircases:
  215. reversals += staircase.reversalIntensities[-reversals_to_use:]
  216. JND = np.mean(reversals)
  217. # Generate tone sequences based on the individual's JND
  218. generate_sequences(standard_freq, tone_name, JND, difficulties + [practice_difficulty], standard_ioi, intervals,
  219. base_intervals=5, mod_intervals=1, sr=44100,
  220. tone_dir='stimuli/tones/', out_dir='stimuli/S%s/' % info_dict['subject'])
  221. ###
  222. # MAIN TASK
  223. ###
  224. text.setText('Up or Down?')
  225. text.draw()
  226. win.flip()
  227. event.waitKeys(keyList=['space'], clearEvents=True)
  228. win.flip()
  229. # Loop through trials
  230. trial_number = 1 # Start on trial 1
  231. block_number = 0 # Start on block 0 (practice section)
  232. for trial in trials:
  233. ###
  234. # PRETRIAL
  235. ###
  236. # Load stimulus sequence for this trial during the pretrial delay
  237. pretime = core.StaticPeriod(screenHz=frame_rate, win=win)
  238. pretime.start(pretrial_delay)
  239. shift = trial.shift
  240. interval = trial.interval
  241. difficulty = trial.difficulty
  242. stimulus = sound.Sound('stimuli/S%s/sequence_%s%s%s_%i.wav' % (info_dict['subject'], tone_name, shift, difficulty, interval))
  243. text.setText('+')
  244. text.draw()
  245. pretime.complete()
  246. # Display fixation cross and play the simulus sequence
  247. win.flip()
  248. stimulus.play()
  249. # Wait for the sequence to end
  250. text.setText('Was the final tone higher or lower in pitch?')
  251. text.draw()
  252. core.wait(3)
  253. while not stimulus.status == constants.FINISHED:
  254. core.wait(.01)
  255. # Prompt for the participant's response and map up/down to +/-
  256. win.flip()
  257. response_period_start = core.getAbsTime()
  258. response = event.waitKeys(keyList=['up', 'down'], clearEvents=True)
  259. rt = core.getAbsTime() - response_period_start
  260. if 'up' in response:
  261. response = '+'
  262. elif 'down' in response:
  263. response = '-'
  264. else:
  265. response = None
  266. win.flip()
  267. # Save data
  268. trials.addData('shift_size', JND * difficulty)
  269. trials.addData('response', response)
  270. trials.addData('rt', rt)
  271. trials.addData('jnd', JND)
  272. trials.addData('correct', int(shift == response))
  273. exp.nextEntry()
  274. ###
  275. # END OF PRACTICE
  276. ###
  277. # If this was the final trial of the practice block (0), end the practice
  278. if block_number == 0 and trial_number == n_practice_trials_per_shift * len(shifts):
  279. text.setText('You have completed the practice trials!')
  280. text.draw()
  281. win.flip()
  282. event.waitKeys(keyList=['space'], clearEvents=True)
  283. block_number += 1
  284. trial_number = 0
  285. ###
  286. # POST-BLOCK BREAK
  287. ###
  288. # If this was the final trial in a block, start a break
  289. elif trial_number == trials_per_block and block_number != blocks:
  290. text.setText('You have completed section %i of %i!\nWhen you are ready to continue, press SPACEBAR to begin the next section.' % (block_number, blocks))
  291. text.draw()
  292. win.flip()
  293. event.waitKeys(keyList=['space'], clearEvents=True)
  294. block_number += 1
  295. trial_number = 0
  296. # If this was the final trial in the last block we have time for, stop presenting trials
  297. elif trial_number == trials_per_block and block_number == blocks:
  298. break
  299. # Move to next trial number
  300. trial_number += 1
  301. ###
  302. # POST-EXPERIMENT
  303. ###
  304. # After completing all trials, display the ending message
  305. text.setText('You have completed section %i of %i!\nThank you for participating! Please let the researcher know you have finished.' % (block_number, blocks))
  306. text.draw()
  307. win.flip()
  308. # Data should save automatically, but manually save a backup copy just in case
  309. exp.saveAsWideText('data/%s_%s.csv' % (experiment_name, info_dict['subject']))
  310. # Press any key to close the window, then exit
  311. event.waitKeys(clearEvents=True)
  312. win.close()
  313. core.quit()

experiment_ip_adaptive.py at commit 4c6706b, under CC-BY-4.0 · at the source

Overview

Authors: Jesse K. Pazdera1, Olive M. Rinaldi1, Laurel J. Trainor1,2,3
  1. Department of Psychology, Neuroscience and Behaviour, McMaster University,Hamilton, ON Canada
  2. McMaster Institute for Music and the Mind, Hamilton, ON Canada
  3. Rotman Research Institute, Baycrest Hospital,Toronto, ON Canada
Institutions: McMaster University (Canada); Baycrest Hospital (Canada)
Journal: Scientific reports, volume 16, issue 1, article 23288
Dates: received 24 October 2024; accepted 12 May 2026; published online 21 May 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41598-026-53525-0 · PMID 42168510 · PMCID PMC13402612 · OpenAlex W4401475543
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: human (organism), cognitive (subfield)
Methods: Statistics, Connectivity, Spectral & time-frequency
Keywords: Illusion, Perceptual bias, Perceptual integration, Pitch discrimination, Rhythmic timing, Human behaviour, Auditory system
MeSH: Illusions*, Pitch Perception*, Time Perception*, Acoustic Stimulation, Female, Humans, Male, Pitch Discrimination, Time Factors (* major topic)
Topic: Music Technology and Sound Studies (Computer Vision and Pattern Recognition, Computer Science), according to OpenAlex
Citations: not cited yet (Europe PMC); 79 references in the paper

Abstract

It has long been proposed that the brain integrates pitch and timing cues during auditory perception. If true, the pitch of a sound should influence its perceived timing, and its timing should influence its perceived pitch. Previous research has found that higher-pitched sounds tend to be perceived as faster than lower-pitched sounds, and in the present study we investigated whether sounds that arrive earlier or later than expected are similarly perceived as higher or lower in pitch. In Experiment 1, participants heard isochronous, repeating standard tones followed by a pitch-shifted probe, and indicated if the pitch increased or decreased. We observed a strong biasing effect of the probe’s timing on its perceived pitch, such that later probes were more likely to be perceived as lower than the standard. Correct, bias-conforming responses to mistimed probes were also significantly faster than responses to on-beat probes. In Experiment 2, we used an adaptive difficulty procedure to investigate whether this timing-induced bias strengthens under conditions of low discriminability. We did not find evidence that bias varies with the magnitude of pitch change or with individual differences in pitch sensitivity. In conjunction with past findings of pitch-induced illusory timing changes, our results support the hypothesis that pitch and time are perceptually integrated. We discuss this integration within a Bayesian predictive coding framework, as possibly learned from real-world correlations between pitch and timing that derive from latent properties of sound sources.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

Its files are read in the Code ↔ Paper reader above, with 14 matches between paragraphs and lines of code.

OSF hrj3t

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Languages: Jupyter (7), R (2), JavaScript (1), Python (1)
Size: 213 files, 11 scripts
Software Heritage: not checked
Found in: “Data availability”
Holds: README, 7 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: NumPy (8 files), pandas (4 files), SciPy (4 files), Matplotlib (3 files), seaborn (3 files), lme4 (2 files), lmerTest (2 files), tidyverse (2 files), car (1 file), PsychoPy (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
  • 28 September 2026: the link answers (HTTP 200)
12 files
At the source: osf.io/hrj3t/

jpazdera/IllusoryPitch

License: CC-BY-4.0
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 4c6706b4423ec62a722ec46ddb766f11a1143444, 20 May 2026
Languages: Jupyter (12), R (2), JavaScript (1), Python (1)
Size: 1,457 files, 16 scripts
Software Heritage: not archived
Found in: “Data availability”
Holds: README, 12 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: NumPy (13 files), pandas (8 files), SciPy (8 files), Matplotlib (7 files), seaborn (7 files), lme4 (2 files), lmerTest (2 files), tidyverse (2 files), car (1 file), PsychoPy (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
17 files

The paper's code and data availability statement is in the Data section.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 27 scripts, each with its path and the digest of its content;
  • 14 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability

We have made all data, code, and stimuli from both experiments publicly available on the Open Science Framework at https://osf.io/hrj3t/, as well as on GitHub at https://github.com/jpazdera/IllusoryPitch.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 2, 28 September 2026

  • Funding: added Canadian Institute for Advanced Research; Canadian Institutes of Health Research: 153130, MOP153130; Natural Sciences and Engineering Research Council of Canada: rgpin-2019-05416, RGPIN-2019

Version 1, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 3 authors, 7 keywords, 9 MeSH terms, 74 references.

Cite

This paper

Pazdera, J. K., Rinaldi, O. M., & Trainor, L. J. (2026). Timing-induced illusory percepts of pitch. Scientific reports, 16(1), 23288. https://doi.org/10.1038/s41598-026-53525-0

BibTeX

@article{pazdera2026timing,
author = {Pazdera, Jesse K. and Rinaldi, Olive M. and Trainor, Laurel J.},
title = {{Timing-induced illusory percepts of pitch}},
journal = {Scientific reports},
year = {2026},
month = may,
volume = {16},
number = {1},
pages = {23288},
publisher = {Nature Publishing Group},
issn = {2045-2322},
doi = {10.1038/s41598-026-53525-0},
url = {https://doi.org/10.1038/s41598-026-53525-0},
pmid = {42168510},
pmcid = {PMC13402612}
}

RIS

TY - JOUR
AU - Pazdera, Jesse K.
AU - Rinaldi, Olive M.
AU - Trainor, Laurel J.
TI - Timing-induced illusory percepts of pitch
T2 - Scientific reports
J2 - Sci Rep
PY - 2026
DA - 2026/05/21
VL - 16
IS - 1
SP - 23288
SN - 2045-2322
PB - Nature Publishing Group
DO - 10.1038/s41598-026-53525-0
UR - https://doi.org/10.1038/s41598-026-53525-0
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41598-026-53525-0",
"type": "article-journal",
"title": "Timing-induced illusory percepts of pitch",
"container-title": "Scientific reports",
"author": [
{
"family": "Pazdera",
"given": "Jesse K."
},
{
"family": "Rinaldi",
"given": "Olive M."
},
{
"family": "Trainor",
"given": "Laurel J."
}
],
"container-title-short": "Sci Rep",
"volume": "16",
"issue": "1",
"page": "23288",
"DOI": "10.1038/s41598-026-53525-0",
"PMID": "42168510",
"PMCID": "PMC13402612",
"ISSN": "2045-2322",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41598-026-53525-0",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
21
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1038/s41598-026-41129-7 [code]
Non-linear relationships between auditory mismatch responses and the inharmonicity of complex sounds.
Journal: Scientific reports
In common: PsychoPy, lmerTest, lme4, 6 other tools, cognitive, 3 references
[2] doi:10.34133/csbj.0042 [code]
Using Steady-State Visual Evoked Potentials to Characterize Wide-Ranging Retinopathy Linked to &lt;i&gt;CRB1&lt;/i&gt;: Implications for Clinical Trials.
Journal: Computational and structural biotechnology journal
In common: PsychoPy, car, lmerTest, 7 other tools, 1 reference
[3] doi:10.7554/elife.107088 [code]
Development of auditory and spontaneous movement responses to music over the first postnatal year.
Journal: eLife
In common: car, lme4, seaborn, 5 other tools, 3 references
[4] doi:10.1038/s41467-026-73865-9 [code]
Histamine shapes the neurocomputational dynamics of human learning.
Journal: Nature communications
In common: PsychoPy, car, lmerTest, 7 other tools, cognitive
[5] doi:10.1167/jov.26.8.4 [code]
The neural processes of illusory occlusion in object recognition.
Journal: Journal of vision
In common: PsychoPy, seaborn, tidyverse, 4 other tools, cognitive, 2 references
[6] doi:10.1162/imag.a.105 [code]
Right posterior theta reflects human parahippocampal phase resetting by salient cues during goal-directed navigation
Journal: n/a
In common: car, lmerTest, lme4, 6 other tools, cognitive
[7] doi:10.1523/eneuro.0076-26.2026 [code]
Exogenously Driven Neural Reactivation of Spatially Matching Visual Working-Memory Contents.
Journal: eNeuro
In common: PsychoPy, car, lme4, 5 other tools, cognitive
[8] doi:10.1162/imag.a.1321 [code]
Phase similarity between similar objects indicates representational merging across retrieval training but not sleep.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: car, lmerTest, lme4, 6 other tools, cognitive
[9] doi:10.1038/s41467-026-74743-0 [code]
Meta-analytic evidence for distinct neural correlates of conditioned versus verbally induced placebo analgesia.
Journal: Nature communications
In common: lmerTest, lme4, seaborn, 4 other tools, 2 references
[10] doi:10.1073/pnas.2603114123 [code]
The human hippocampus can pattern separate memories by meaning.
Journal: Proceedings of the National Academy of Sciences of the United States of America
In common: PsychoPy, lmerTest, lme4, 5 other tools, cognitive

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.