Reaction time analyzer

Reaction time analyzer

Script used to estimate voice activity. Use of the demo window to run through lots of files. Some tricks to detect steepest rise.

#form Reaction time analyzer
#       sentence majorPath C:\Users\ling-jfr\Dropbox\Atttittapådata
#       natural currentSweep 1
#endform

# commented to get sane syntax highlighing in the wiki
#majorPath$="C:\Users\ling-jfr\Dropbox\Atttittapådata"
##anaFile$="C:\Users\ling-jfr\Dropbox\Atttittapådata\analysis.txt"
#anaFile$="C:\Users\ling-jfr\Documents\Praat\analysis.txt"
createAnalysisFile=0

nocheck select all
nocheck Remove
Erase all
#clearinfo

currentSweep=1
# find unanalyzed
if fileReadable(anaFile$)
        anaStrings=Read from file... 'anaFile$'
        numStr=Get number of strings
        for i from 1 to numStr
                cStr$=Get string... i
                if cStr$=="false"
                        currentSweep=i
                        i=numStr
                endif
        endfor
endif
#currentSweep=1

wavTop=95
wavBottom=65
specTop=70
specBottom=40
garnish$="yes"
analyzed=0

# commented to get sane syntax highlighing in the wiki
#if windows
#  separator$ = "\"
#else
#  separator$ = "/"
#endif

timeRange1=0
timeRange2=0

# create notch filter
#lowSteep = sqrt(ln(2))
#lowFreq = 430
#beta = sqrt(ln(2))
#highFreq = 2000
#filterSound=Create Sound from formula... filter 1 -0.2 0.2 44100 2*pi*sqrt(pi)*highFreq/beta*exp(-(pi*x*highFreq/beta)^2) - 4*pi*sqrt(pi)*lowFreq/lowSteep*exp(-(pi*x*lowFreq/lowSteep)^2)

# lpc filter
lpcfilter=Read from file... C:\Users\ling-jfr\Dropbox\Atttittapådata\lpcfilter.LPC

# run through dir and subdirs and look for wavs
# store them in Strings object wavStrings
dirWithWavs=0
dirGlobPath$=majorPath$+separator$+"*"
strings1 = Create Strings as directory list... directoryList1 'dirGlobPath$'
nStrings1=Get number of strings
for i from 1 to nStrings1
        select 'strings1'
        currentStringi$=Get string... i
        subDirGlobPath$=majorPath$+separator$+currentStringi$
        strings2 = Create Strings as directory list... directoryList2 'subDirGlobPath$'
        nStrings2=Get number of strings
        for j from 1 to nStrings2
                select 'strings2'
                currentStringj$=Get string... j
                wavGlobPath$=subDirGlobPath$+separator$+currentStringj$+separator$+"*.wav"
                strings3 = Create Strings as file list... fileList 'wavGlobPath$'
                nStrings3=Get number of strings
                for k from 1 to nStrings3
                        select 'strings3'
                        currentStringk$=Get string... k
                        wavName$=subDirGlobPath$+separator$+currentStringj$+separator$+currentStringk$
                        Set string... k 'wavName$'
                endfor

                if nStrings3 > 0
                        dirWithWavs=dirWithWavs+1
                endif
                if dirWithWavs==1
                        select 'strings3'
                        Copy... appended
                        wavStrings=selected("Strings")
                endif
                if dirWithWavs > 1
                        select 'wavStrings'
                        plus 'strings3'
                        newWavStrings=Append
                        select 'wavStrings'
                        Remove
                        select 'newWavStrings'
                        wavStrings=selected("Strings")
                endif
                select 'strings3'
                Remove
        endfor
        select 'strings2'
        Remove
endfor
select 'strings1'
Remove

select 'wavStrings'
numWav=Get number of strings
# we should save the wavStrings with the anaFile so
# we're safe if the wav structure is changed

# create an analysis file
if createAnalysisFile
        for i from 1 to numWav
                Set string... i false
        endfor
        Save as short text file... 'anaFile$'
        exit
endif

goto GETDATA

label CLEANDATA
select 's1'
plus 's2'
plus 's4'
plus 'spec1'
plus 'i1'
plus 'tg1'
Remove
goto GETDATA

label GETDATA
select 'wavStrings'
currentStringi$=Get string... currentSweep
s1=Read from file... 'currentStringi$'
startSound = Get start time
endSound = Get end time
startIv = startSound
endIv = endSound
durIv = endIv - startIv
plus 'lpcfilter'
s4=Filter (inverse)
Scale intensity... 70
spec1=noprogress To Spectrogram... 0.005 5000 0.002 20 Gaussian
select 's4'
s2=noprogress Deepen band modulation... 20 300 8000 3 30 100
Scale intensity... 70

select 's2'
i1=To Intensity... 75 0 yes
Formula... if x < 0.2 || x > 1.5 then 0 else self fi

keep = 0
noMoreCheck = 0
numberOfLevels = 5
for i from 1 to numberOfLevels
        thresh = -5-(i*5)
        select 'i1'
        tg'i' = To TextGrid (silences)... thresh 0.1 0.12 silent sounding
        countSounding=Count labels... 1 sounding
        if countSounding > 1 && keep > 0
                noMoreCheck=1          
        endif
        if countSounding == 1 && noMoreCheck == 0
                if i > 1
                        lastDurIv = durIv
                endif
                call GetBounds
                if i > 1
                        tIncrease = durIv / lastDurIv
                else
                        tIncrease = 1
                endif
                keep = i

#               # prevent overlong increase between 20 and 25
#               if i == 4
#                       printline overlong increase 'currentSweep' 'i': ('tIncrease')
#                       if tIncrease > 1.25
#                               keep = 3
#                               noMoreCheck = 1
#                               printline overlong increase 'currentSweep' 'i': ('tIncrease')
#                       else
#                               keep = 4
#                       endif
#               endif


                # prevent overlong increase between 25 and 30
                if i == 5
                        if tIncrease > 1.5
                                keep = 4
                                noMoreCheck = 1
#                               printline overlong increase 'currentSweep' 'i': ('tIncrease')
                        else
                                keep = 5
                        endif
                endif
        endif
endfor

if keep > 0
        dum = tg'keep'
        select 'dum'
        tgfin = Copy...
else
        select 'i1'
        tgfin = To TextGrid (silences)... -200 0.1 0.1 silent sounding
endif

select 'tg1'
for i from 2 to numberOfLevels
        dum = tg'i'
        plus 'dum'
endfor
Remove

select 'tgfin'
tg1=selected("TextGrid")

select 'i1'
call findRise
tg2=selected("TextGrid")
plus 'tg1'
tgboth=Merge
select 'tg1'
plus 'tg2'
Remove
select 'tgboth'
tg1=selected("TextGrid")


startIv = startSound
endIv = endSound
durIv = endIv - startIv
call GetBounds
goto REDRAW

procedure GetBounds
#indent
nInt=Get number of intervals... 1
for .i from 1 to nInt
        lab$=Get label of interval... 1 .i
        if lab$=="sounding"
                startIv=Get start point... 1 .i
                endIv=Get end point... 1 .i
                durIv = endIv - startIv
        endif
endfor
select 'i1'
dbAtStartIv=Get value at time... startIv Cubic
#indent
endproc


label REDRAW
demo Erase all
demo Select outer viewport... 0 100 0 100
demo Axes... 0 100 0 100
demo Black
demo Line width... 1
demo Solid line

# Title
demo Text... 50 centre 100 top 'currentStringi$' ('currentSweep'/'numWav')

# buttons
call DrawButton 0 20 12 18 Prev
call DrawButton 25 45 12 18 Reject
call DrawButton 50 70 12 18 Accept
call DrawButton 75 95 12 18 Next

call DrawButton 12 32 24 30 Target
call DrawButton 37 58 28 34 Before
call DrawButton 37 58 20 26 After
call DrawButton 63 83 24 30 All

procedure DrawButton .leftX .rightX .topY .bottomY .buttonText$
        demo Paint rectangle... pink .leftX .rightX .topY .bottomY
        demo Draw rectangle... .leftX .rightX .topY .bottomY
        .textX = (.rightX + .leftX) / 2
        .textY = (.topY + .bottomY) / 2
        demo Text... .textX centre .textY half '.buttonText$'
endproc

# waveform
demo Select outer viewport... 0 100 'wavBottom' 'wavTop'
select 's4'
plus 'tg1'
demo Draw... timeRange1 timeRange2 yes yes yes
demo Red
demo Solid line
demo Line width... 3
demo Draw rounded rectangle... startIv endIv 1 -1 3
demo Line width... 1

# spectrogram
demo Select outer viewport... 0 100 'specBottom' 'specTop'
select 'spec1'
demo Paint... timeRange1 timeRange2 0 0 100 yes 50 6 0 yes
select 'i1'
demo Line width... 2
demo Draw... timeRange1 timeRange2 0 0 no

myDemoX1=timeRange1
myDemoX2=timeRange1
currentMark=1
goto WAIT

label WAIT
while demoWaitForInput ( )
        if demoClicked ( )
                demo Select outer viewport... 0 100 0 100
                demo Axes... 0 100 0 100
                goto PREV demoClickedIn (0, 20, 12, 18)
                goto REJECT demoClickedIn (25, 45, 12, 18)
                goto ACCEPT demoClickedIn (50, 70, 12, 18)
                goto NEXT demoClickedIn (75, 95, 12, 18)

                goto PLAYTARGET demoClickedIn (12, 32, 24, 30)
                goto PLAYBEFORE demoClickedIn (37, 58, 28, 34)
                goto PLAYAFTER demoClickedIn (37, 58, 20, 26)
                goto PLAYALL demoClickedIn (63, 83, 24, 30)

                #demo Undo

                #demo Select outer viewport... 0 100 'specBottom' 'specTop'
                #demo Axes... 0 'soundDur' 0 5000
                #goto GETMOUSEX demoClickedIn (0, soundDur, 0, 5000)
                #demo Undo
        endif
        #goto GETMOUSEX demoClickedIn (0, soundDur, 0, 5000)
        #goto PLAY demoClickedIn
        #goto MARKLEFT demoInput ("1")
        #goto MARKRIGHT demoInput ("2")
        goto EXIT demoInput ("x")
        goto ACCEPT demoInput (" ")
        goto REJECT demoInput ("r")
        goto PLAYTARGET demoInput ("t")
        goto PLAYALL demoInput ("a")
        goto ERROR demoInput("e")
endwhile
pause Why are we here?

label ACCEPT
select 'anaStrings'
Set string... currentSweep 'startIv:3'
Save as short text file... 'anaFile$'
goto NEXT

label REJECT
select 'anaStrings'
Set string... currentSweep reject
Save as short text file... 'anaFile$'
goto NEXT

label ERROR
select 'anaStrings'
Set string... currentSweep error
Save as short text file... 'anaFile$'
goto NEXT

label NEXT
#demo Undo
currentSweep=currentSweep+1
goto CLEANDATA

label PREV
#demo Undo
currentSweep=currentSweep-1
goto CLEANDATA

label EXIT
demo Select outer viewport... 0 100 0 100
demo Axes... 0 100 0 100
demo Text... 50 centre 0 bottom Script has finished. Please close this window manually...
exit

label PLAYTARGET
startPlay = startIv
endPlay = endIv
goto PLAY

label PLAYBEFORE
startPlay = startSound
endPlay = startIv
goto PLAY

label PLAYAFTER
startPlay = endIv
endPlay = endSound
goto PLAY

label PLAYALL
startPlay = startSound
endPlay = endSound
goto PLAY

label PLAY
select 's4'
s3=Extract part... startPlay endPlay rectangular 1 no
Play
Remove
goto WAIT

# unused
procedure useVoicing
select 's2'
pp1=noprogress To PointProcess (periodic, cc)... 75 600
tg2=To TextGrid (vuv)... 0.02 0.01
nInt=Get number of intervals... 1
myLowest=100
moveTo=0
for i from 1 to nInt
        lab$=Get label of interval... 1 i
        if lab$=="V"
                startVIv=Get start point... 1 i
                diff=abs(startIv-startVIv)
                if diff < myLowest
                        myLowest = diff
                        moveTo=startVIv
                endif  
        endif
endfor
startIv=moveTo

plus 'tg1'
tgboth=Merge
select 'tg1'
plus 'tg2'
plus 'pp1'
Remove
select 'tgboth'
tg1=selected("TextGrid")
endproc


procedure findRise
        .i1=selected("Intensity")
        .m1=Down to Matrix
        .s1=To Sound
        .pp1=To PointProcess (extrema)... 1 yes no Sinc70
        select '.i1'
        #call Acceleration
        call Curvature
        #call Velocity
        .s2=selected("Sound")
        .pp2=To PointProcess (extrema)... 1 yes no Sinc70
if 1
        np1=Get number of points
        candidateIndex=0
        for cp1 from 1 to np1
                select '.pp2'
                accStartTime=Get time from index... cp1
                if accStartTime > 0.2 && accStartTime < 1.5
                select '.pp1'
                disPeakIndex=Get high index... accStartTime
                if disPeakIndex = undefined
                        # some exceptional action
                else
                        disPeakTime=Get time from index... disPeakIndex
                        if disPeakTime = undefined
                                # some exceptional action
                        else
                                candidateIndex=candidateIndex+1
                                select '.i1'
                                accStartVal=Get value at time... accStartTime Cubic
                                disPeakVal=Get value at time... disPeakTime Cubic
                                valDiff=disPeakVal-accStartVal
                                #printline AccIndex: 'cp1' DisPeakIndex: 'disPeakIndex'
                                #       ... AccStartTime: 'accStartTime:3' DisPeakTime: 'disPeakTime:3'
                                #       ... AccStartVal: 'accStartVal:3' DisPeakVal: 'disPeakVal:3'
                                #       ... ValDiff: 'valDiff:3'
                                sTime'candidateIndex'=accStartTime
                                eTime'candidateIndex'=disPeakTime      
                                valD'candidateIndex'=valDiff
                        endif
                endif
                endif
        endfor
endif


if 1
        max=0
        indexOfMax=0
        for cCand from 1 to candidateIndex
                if valD'cCand'>=max
                        max = valD'cCand'
                        indexOfMax=cCand
                endif
        endfor
        select '.s1'
        .tg1=To TextGrid... rise
        Insert boundary... 1 sTime'indexOfMax'
        Insert boundary... 1 eTime'indexOfMax'
        Set interval text... 1 2 rise
endif

        select '.pp2'
        plus '.s2'
        plus '.pp1'
        plus '.s1'
        plus '.m1'
        Remove
        select '.tg1'
endproc

procedure Curvature
        .m1=Down to Matrix
        Rename... '.m1'
        .m2=Copy... Velocity
        Rename... '.m2'
        Formula... (Matrix_'.m1'[col+1]-Matrix_'.m1'[col-1])/2*dx
        Formula... if col == 1 || col == ncol then 0 else self fi
        .m3=Copy... Acceleration
        Rename... '.m3'
        Formula... (Matrix_'.m2'[col+1]-Matrix_'.m2'[col-1])/2*dx
        Formula... if col == 1 || col == ncol then 0 else self fi
        select '.m1'
        Formula... Matrix_'.m3'[col]/(1+Matrix_'.m2'[col]^2)^1.5
        .s1=To Sound
        Rename... '.s1'
        select '.m1'
        plus '.m2'
        plus '.m3'
        Remove
        select '.s1'
endproc

Screenshot (at google drive)