Psychopy中从CSV文件播放的声音叠加问题(以帧为计时单位)
解决PsychoPy中CSV播放声音叠加的问题
嘿,我之前做类似听觉实验时也踩过声音叠加的坑,结合你的实验场景(300ms/18帧的声音时序)和给出的代码片段,给你几个实用的解决方案:
1. 跟踪并控制当前播放的声音实例
最常见的问题就是前一个声音还没播放完毕,下一个就启动了。我们可以用一个变量跟踪当前正在播放的声音,每次播放新声音前做检查处理:
from psychopy import sound # 别忘了导入sound模块 # 初始化变量跟踪当前声音 current_sound = None win = visual.Window() # 假设你已创建实验窗口 # 读取CSV刺激列表(替换成你的读取逻辑) stimuli = [] with open('your_stimuli.csv', 'r') as f: reader = csv.DictReader(f) for row in reader: stimuli.append(row) frame_count = 0 for stim in stimuli: # 处理前一个声音:如果还在播放,停止它(或等待结束,依实验需求选择) if current_sound is not None and current_sound.isPlaying: current_sound.stop() # 若需要等前一个声音自然结束,替换为 current_sound.wait() # 加载并播放当前声音 current_sound = sound.Sound(stim['sound_path']) # 替换为你CSV中的声音文件列名 current_sound.play() # 严格按帧计时,等待18帧 for _ in range(18): win.flip() frame_count += 1
2. 用帧计数器精准控制播放间隔
如果实验依赖严格的帧同步,最好用窗口flip()来计数,避免time.sleep()这类受系统延迟影响的方法:
from psychopy import sound, visual, csv win = visual.Window() current_sound = None frame_count = 0 last_play_frame = -100 # 初始值确保第一次能正常播放 # 读取CSV刺激列表 stimuli = [] with open('your_stimuli.csv', 'r') as f: stimuli = list(csv.DictReader(f)) while frame_count < len(stimuli)*18: win.flip() frame_count += 1 # 每18帧触发一次声音播放 if (frame_count - last_play_frame) == 18: # 停止前一个声音 if current_sound is not None and current_sound.isPlaying: current_sound.stop() # 获取当前要播放的刺激 stim_idx = (frame_count // 18) - 1 if stim_idx < len(stimuli): current_sound = sound.Sound(stimuli[stim_idx]['sound_path']) current_sound.play() last_play_frame = frame_count
3. 利用PsychoPy内置TrialHandler管理时序
PsychoPy的TrialHandler已经封装了刺激时序和资源管理,用它能减少手动控制的出错概率:
from psychopy import sound, visual, data win = visual.Window() current_sound = None # 直接从CSV导入刺激列表创建TrialHandler trials = data.TrialHandler( trialList=data.importConditions('your_stimuli.csv'), nReps=1, method='sequential' # 按CSV顺序播放 ) for trial in trials: # 等待前一个声音结束(确保不叠加) if current_sound is not None: current_sound.wait() # 播放当前声音 current_sound = sound.Sound(trial['sound_path']) current_sound.play() # 等待18帧 for _ in range(18): win.flip() # 可选:记录播放相关数据 trials.addData('play_end_frame', win.getFutureFlipTime(clock='frame'))
额外注意点
- 验证声音文件时长:用Audacity等工具确认你的声音文件实际是300ms,文件时长不符会直接打乱时序
- 调整音频缓冲:如果用pyo库,偶尔会因缓冲导致延迟,可尝试调整
Sound的bufferSize参数,比如sound.Sound(..., bufferSize=512) - 开启帧日志排查:用
logging.console.setLevel(logging.DEBUG)可以查看每帧时间,帮助定位时序问题
内容的提问来源于stack exchange,提问作者looking for answers
相关产品推荐
相关产品推荐

