1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PsychoPy Soundのduration制御について

Last updated at Posted at 2022-07-05

はじめに

PsychoPyで実験タスクのバックグラウンドでメトロノームを鳴らす実装でハマったので,Soundコンポーネントの挙動から洗い出して整理しました.
基本的に実装はBuilderで完結させます.
ちなみにM1MacではPsychoPy自体の挙動がおかしい時がある気がしますね...

環境

  • macOS Monterey v12.3.1 (M1チップ)
  • PsychoPy standalnoe v2021.2.3

概要

ハマりポイントとしては,Builderが生成するコード(hogehoge_lastrun.py)にdurationに関与するパラメータが複数あるというか,Soundコンポーネントの仕様が以下のようであるという点です.

制御の概要図としてはこんな感じ.
ざっくりいうと,SoundコンポーネントのConstructer引数のsecsとstop()メソッドを呼ぶタイミングの整合性が取れていないと,(おそらく)無音状態が再生され続けるというものです.
手っ取り早く解決するには,secsを十分大きく取ってやれば良いはず.
image.png

Builderで生成されるコード

Builder生成コードの挙動確認

以下のような構成で検証します.Soundコンポーネント(mtr)以外は無視してもらって構いません.
スクリーンショット 2022-07-01 12.34.11.png

このpsyexpファイルからコードを生成.
mtrのduration制御に関係がある箇所は,以下3つ.
#エディタからそのままコピペしたのでインデント崩れはご了承ください.

hogehoge_lastrun.py
# 1つ目
mtr = sound.Sound('A', secs=.2, stereo=True, hamming=True,
    name='mtr')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2つ目
    # update component parameters for each repeat
    mtr.setSound('A', secs=.1, hamming=True)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3つ目
        if mtr.status == STARTED:
            # is it time to stop? (based on global clock, using actual start)
            if tThisFlipGlobal > mtr.tStartRefresh + .1-frameTolerance:
                # keep track of stop time/frame for later
                mtr.tStop = t  # not accounting for scr refresh
                mtr.frameNStop = frameN  # exact frame index
                win.timeOnFlip(mtr, 'tStopRefresh')  # time at next scr refresh
                mtr.stop()
  • 1,2つ目のsecs
    • 音が鳴り続ける時間を定義するパラメータ
    • 後述するmtr.status==STARTEDのままということから推察するに,secsは実際に音が鳴る時間を指し,その後はstop()が呼ばれるまで無音が再生されるという事のよう
  • 3つ目のIf文内のstop()
    • 時間判定し,stopするという処理
    • stop()が実行されると,mtr.status==FINISHEDつまり終了(停止)状態となる

つまり,secsより後にstop()を呼ぶように実装してしまうと,実装者はstopのタイミングで音が止まることを期待するが,実際のプログラムはsecsの時間経過後に音が止まる(無音状態になり)ので,意図した時間よりも早く音が止まってしまうということになりかねる.
→secとstop判定する時間の大小関係に注意!!

#特に,メトロノームのような音の繰り返し処理をしたいときに,codeコンポーネントをごにょごにょするとハマる!

statusについて

  • NOT_STARTED:play()以前の状態
  • STARTED:play()実行後の状態
  • FINISHED:stop()実行後の状態
    という具合に確認できたので,secs経過後=無音状態が再生されているのではと推測した.

同じSoundコンポーネントで繰り返し再生する場合は,FINISHED後にstatus = NOT_STARTEDと戻してやれば,再度play()を呼ぶと再生される.

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?