CelebChat / rtvc /speed_changer /myspsolution.praat
lhzstar
initial commits
6bc94ac
raw
history blame
18.6 kB
###########################################################################
# The library was developed based upon the idea introduced #
# by Nivja DeJong and Ton Wempe [1], Paul Boersma and David Weenink [2], #
# Carlo Gussenhoven [3], #
# S.M Witt and S.J. Young [4] #
# Peaks in intensity (dB) that are preceded and followed by dips in #
# intensity are considered as potential syllable cores. #
# #
# Praat Script voice analysis #
# Copyright (C) 2017 Shahab Sabahi #
# #
# This program is a Mysolutions software intellectual property: #
# you can redistribute it and/or modify it under the terms #
# of the Mysolutions Permision. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# #
###########################################################################
#
# modified 2018 July by Shahab Sabahi,
# bug fixed concerning summing total pause, May 28th 2017
###########################################################################
clearinfo
# select all
# Remove
form Counting Syllables in Sound Utterances
real Silence_threshold_(dB) -20
real Minimum_dip_between_peaks_(dB) 2
real Minimum_pause_duration_(s) 0.27
boolean Keep_Soundfiles_and_Textgrids 1
sentence soundin
sentence directory
positive Minimum_pitch_(Hz) 80
positive Maximum_pitch_(Hz) 400
positive Time_step_(s) 0.01
endform
# shorten variables
silencedb = 'silence_threshold'
mindip = 'minimum_dip_between_peaks'
showtext = 'keep_Soundfiles_and_Textgrids'
minpause = 'minimum_pause_duration'
# read files
Read from file... 'soundin$'
# use object ID
soundname$ = selected$("Sound")
soundid = selected("Sound")
originaldur = Get total duration
# allow non-zero starting time
bt = Get starting time
# Use intensity to get threshold
To Intensity... 50 0 yes
intid = selected("Intensity")
start = Get time from frame number... 1
nframes = Get number of frames
end = Get time from frame number... 'nframes'
# estimate noise floor
minint = Get minimum... 0 0 Parabolic
# estimate noise max
maxint = Get maximum... 0 0 Parabolic
#get .99 quantile to get maximum (without influence of non-speech sound bursts)
max99int = Get quantile... 0 0 0.99
# estimate Intensity threshold
threshold = max99int + silencedb
threshold2 = maxint - max99int
threshold3 = silencedb - threshold2
if threshold < minint
threshold = minint
endif
# get pauses (silences) and speakingtime
To TextGrid (silences)... threshold3 minpause 0.1 silent sounding
textgridid = selected("TextGrid")
silencetierid = Extract tier... 1
silencetableid = Down to TableOfReal... sounding
nsounding = Get number of rows
npauses = 'nsounding'
speakingtot = 0
for ipause from 1 to npauses
beginsound = Get value... 'ipause' 1
endsound = Get value... 'ipause' 2
speakingdur = 'endsound' - 'beginsound'
speakingtot = 'speakingdur' + 'speakingtot'
endfor
select 'intid'
Down to Matrix
matid = selected("Matrix")
# Convert intensity to sound
To Sound (slice)... 1
sndintid = selected("Sound")
# use total duration, not end time, to find out duration of intdur
# in order to allow nonzero starting times.
intdur = Get total duration
intmax = Get maximum... 0 0 Parabolic
# estimate peak positions (all peaks)
To PointProcess (extrema)... Left yes no Sinc70
ppid = selected("PointProcess")
numpeaks = Get number of points
# fill array with time points
for i from 1 to numpeaks
t'i' = Get time from index... 'i'
endfor
# fill array with intensity values
select 'sndintid'
peakcount = 0
for i from 1 to numpeaks
value = Get value at time... t'i' Cubic
if value > threshold
peakcount += 1
int'peakcount' = value
timepeaks'peakcount' = t'i'
endif
endfor
# fill array with valid peaks: only intensity values if preceding
# dip in intensity is greater than mindip
select 'intid'
validpeakcount = 0
currenttime = timepeaks1
currentint = int1
for p to peakcount-1
following = p + 1
followingtime = timepeaks'following'
dip = Get minimum... 'currenttime' 'followingtime' None
diffint = abs(currentint - dip)
if diffint > mindip
validpeakcount += 1
validtime'validpeakcount' = timepeaks'p'
endif
currenttime = timepeaks'following'
currentint = Get value at time... timepeaks'following' Cubic
endfor
# Look for only voiced parts
select 'soundid'
To Pitch (ac)... 0.02 30 4 no 0.03 0.25 0.01 0.35 0.25 450
# keep track of id of Pitch
pitchid = selected("Pitch")
voicedcount = 0
for i from 1 to validpeakcount
querytime = validtime'i'
select 'textgridid'
whichinterval = Get interval at time... 1 'querytime'
whichlabel$ = Get label of interval... 1 'whichinterval'
select 'pitchid'
value = Get value at time... 'querytime' Hertz Linear
if value <> undefined
if whichlabel$ = "sounding"
voicedcount = voicedcount + 1
voicedpeak'voicedcount' = validtime'i'
endif
endif
endfor
# calculate time correction due to shift in time for Sound object versus
# intensity object
timecorrection = originaldur/intdur
# Insert voiced peaks in TextGrid
if showtext > 0
select 'textgridid'
Insert point tier... 1 syllables
for i from 1 to voicedcount
position = voicedpeak'i' * timecorrection
Insert point... 1 position 'i'
endfor
endif
Save as text file: "'directory$'/'soundname$'.TextGrid"
# use object ID
Read from file... 'soundin$'
soundname$ = selected$("Sound")
soundid = selected("Sound")
fileName$ = "f0points'soundname$'.txt"
# Calculate F0 values
To Pitch... time_step minimum_pitch maximum_pitch
numberOfFrames = Get number of frames
# Loop through all frames in the Pitch object:
select Pitch 'soundname$'
unit$ = "Hertz"
min_Hz = Get minimum... 0 0 Hertz Parabolic
min$ = "'min_Hz'"
max_Hz = Get maximum... 0 0 Hertz Parabolic
max$ = "'max_Hz'"
mean_Hz = Get mean... 0 0 Hertz
mean$ = "'mean_Hz'"
stdev_Hz = Get standard deviation... 0 0 Hertz
stdev$ = "'stdev_Hz'"
median_Hz = Get quantile... 0 0 0.50 Hertz
median$ = "'median_Hz'"
quantile25_Hz = Get quantile... 0 0 0.25 Hertz
quantile25$ = "'quantile25_Hz'"
quantile75_Hz = Get quantile... 0 0 0.75 Hertz
quantile75$ = "'quantile75_Hz'"
# Collect and save the pitch values from the individual frames to the text file:
quantile250 = 'quantile25$'
quantile750 = 'quantile75$'
meanall = 'mean$'
sd='stdev$'
medi='median$'
mini='min$'
maxi='max$'
# clean up before next sound file is opened
select 'intid'
plus 'matid'
plus 'sndintid'
plus 'ppid'
plus 'pitchid'
plus 'silencetierid'
plus 'silencetableid'
Read from file... 'soundin$'
soundname$ = selected$ ("Sound")
To Formant (burg)... 0 5 5500 0.025 50
Read from file... 'directory$'/'soundname$'.TextGrid
int=Get number of intervals... 2
appendInfoLine:"int = ", 'int'
if int<2
warning$="A noisy background or unnatural-sounding speech detected. No result try again"
appendInfoLine: warning$
# exitScript()
endif
# We then calculate F1, F2 and F3
fff= 0
eee= 0
inside= 0
outside= 0
for k from 2 to 'int'
select TextGrid 'soundname$'
label$ = Get label of interval... 2 'k'
if label$ <> ""
# calculates the onset and offset
vowel_onset = Get starting point... 2 'k'
vowel_offset = Get end point... 2 'k'
select Formant 'soundname$'
f_one = Get mean... 1 vowel_onset vowel_offset Hertz
f_two = Get mean... 2 vowel_onset vowel_offset Hertz
f_three = Get mean... 3 vowel_onset vowel_offset Hertz
appendInfoLine: "f_one = ", 'f_one'
appendInfoLine: "f_two = ", 'f_two'
appendInfoLine: "f_three = ", 'f_three'
ff = 'f_two'/'f_one'
lnf1 = 'f_one'
lnf2f1 = ('f_two'/'f_one')
uplim =(-0.012*'lnf1')+13.17
lowlim =(-0.0148*'lnf1')+8.18
f1uplim =(lnf2f1-13.17)/-0.012
f1lowlim =(lnf2f1-8.18)/-0.0148
if lnf1>='f1lowlim' and lnf1<='f1uplim'
inside = 'inside'+1
else
outside = 'outside'+1
endif
fff = 'fff'+'f1uplim'
eee = 'eee'+'f1lowlim'
ffff = 'fff'/'int'
eeee = 'eee'/'int'
pron =('inside'*100)/('inside'+'outside')
prom =('outside'*100)/('inside'+'outside')
prob1 = invBinomialP ('pron'/100, 'inside', 'inside'+'outside')
prob = 'prob1:2'
endif
endfor
lnf0 = (ln(f_one)-5.65)/0.31
f00 = exp (lnf0)
Remove
if showtext < 1
select 'soundid'
plus 'textgridid'
Remove
endif
# summarize results in Info window
speakingrate = 'voicedcount'/'originaldur'
speakingraterp = ('voicedcount'/'originaldur')*100/3.93
articulationrate = 'voicedcount'/'speakingtot'
articulationraterp = ('voicedcount'/'speakingtot')*100/4.64
npause = 'npauses'-1
asd = 'speakingtot'/'voicedcount'
avenumberofwords = ('voicedcount'/1.74)/'speakingtot'
avenumberofwordsrp = (('voicedcount'/1.74)/'speakingtot')*100/2.66
nuofwrdsinchunk = (('voicedcount'/1.74)/'speakingtot')* 'speakingtot'/'npauses'
nuofwrdsinchunkrp = ((('voicedcount'/1.74)/'speakingtot')* 'speakingtot'/'npauses')*100/9
avepauseduratin = ('originaldur'-'speakingtot')/('npauses'-1)
avepauseduratinrp = (('originaldur'-'speakingtot')/('npauses'-1))*100/0.75
balance = ('voicedcount'/'originaldur')/('voicedcount'/'speakingtot')
balancerp = (('voicedcount'/'originaldur')/('voicedcount'/'speakingtot'))*100/0.85
nuofwrds= ('voicedcount'/1.74)
f1norm = -0.0118*'pron'*'pron'+0.5072*'pron'+394.34
inpro = ('nuofwrds'*60/'originaldur')
polish = 'originaldur'/2
# Read the saved pitch points as a Matrix object:
if meanall<150
q25='quantile250'/100
q75='quantile750'/140
mr= 'meanall'/119
else
q25='quantile250'/183
q75='quantile750'/237
mr= 'meanall'/210
endif
# Convert the original minimum and maximum parameters in order to define the x scale of the
if q25<=1 and q75<=1 and mr>=0.95 and mr<=1.05
ins=10
elsif q25<=1 and q75<=1 and mr>=0.9 and mr<=1.1
ins=9
elsif q25<=1 and q75<=1 and mr>=0.85 and mr<=1.15
ins=8
elsif mr>=0.9 and mr<=1.1
ins=7
elsif mr>=0.8 and mr<=1.2
ins=6
elsif mr<=0.8
ins=4
else
ins=5
endif
#SCORING
if f00<90 or f00>255
z=1.16
elsif f00<97 or f00>245
z=2
elsif f00<115 or f00>245
z=3
elsif f00<=245 or f00>=115
z=4
else
z=1
endif
if nuofwrdsinchunk>=6.24 and avepauseduratin<=1.0
l=4
elsif nuofwrdsinchunk>=6.24 and avepauseduratin>1.0
l=3.6
elsif nuofwrdsinchunk>=4.4 and nuofwrdsinchunk<=6.24 and avepauseduratin<=1.15
l=3.3
elsif nuofwrdsinchunk>=4.4 and nuofwrdsinchunk<=6.24 and avepauseduratin>1.15
l=3
elsif nuofwrdsinchunk<4.4 and avepauseduratin<=1.15
l=2
elsif nuofwrdsinchunk<=4.4 and avepauseduratin>1.15
l=1.16
else
l=1
endif
if balance>=0.69 and avenumberofwords>=2.60
o=4
elsif balance>=0.60 and avenumberofwords>=2.43
o=3.5
elsif balance>=0.5 and avenumberofwords>=2.25
o=3
elsif balance>=0.5 and avenumberofwords>=2.07
o=2
elsif balance>=0.5 and avenumberofwords>=1.95
o=1.16
else
o=1
endif
if speakingrate<=4.26 and speakingrate>=3.16
q=4
elsif speakingrate<=3.16 and speakingrate>=2.54
q=3.5
elsif speakingrate<=2.54 and speakingrate>=1.91
q=3
elsif speakingrate<=1.91 and speakingrate>=1.28
q=2
elsif speakingrate<=1.28 and speakingrate>=1.0
q=1.16
else
q=1
endif
if balance>=0.69 and articulationrate>=4.54
w=4
elsif balance>=0.60 and articulationrate>=4.22
w=3.5
elsif balance>=0.50 and articulationrate>=3.91
w=3
elsif balance>=0.5 and articulationrate>=3.59
w=2
elsif balance>=0.5 and articulationrate>=3.10
w=1.16
else
w=1
endif
if inpro>=119 and ('f1norm'*1.1)>=f1lowlim
r = 4
elsif inpro>=119 and ('f1norm'*1.1)<f1lowlim
r = 3.8
elsif inpro<119 and inpro>=100 and ('f1norm'*1.1)>=f1lowlim
r = 3.6
elsif inpro<119 and inpro>=100 and ('f1norm'*1.1)<f1lowlim
r = 3.4
elsif inpro<100 and inpro>=80 and ('f1norm'*1.1)>=f1lowlim
r= 3.2
elsif inpro<100 and inpro>=80 and ('f1norm'*1.1)<f1lowlim
r = 2.8
elsif inpro<80 and inpro>=70 and ('f1norm'*1.1)>=f1lowlim
r = 2.4
elsif inpro<70 and inpro>=60 and ('f1norm'*1.1)>=f1lowlim
r = 2
elsif inpro<70 and inpro>=60 and ('f1norm'*1.1)<f1lowlim
r = 1.1
else
r = 0.3
endif
if articulationrate>=4.80 and balance>=0.8
qr = 4
elsif articulationrate>=4.80 and balance<0.8
qr = 3.8
elsif articulationrate<4.80 and articulationrate>=4.65 and balance>=0.8
qr = 3.6
elsif articulationrate<4.80 and articulationrate>=4.65 and balance<0.8
qr = 3.4
elsif articulationrate<4.65 and articulationrate>=4.55 and balance>=0.8
qr= 3.2
elsif articulationrate<4.65 and articulationrate>=4.55 and balance<0.8
qr = 2.8
elsif articulationrate<4.55 and articulationrate>=4.40 and balance>=0.8
qr = 2.4
elsif articulationrate<4.40 and articulationrate>=4.30 and balance>=0.8
qr = 2
elsif articulationrate<4.40 and articulationrate>=4.30 and balance<0.8
qr = 1.5
else
qr = 1
endif
# summarize SCORE in Info window
totalscore =(l*2+z*4+o*3+qr*3+w*4+r*4)/20
totalscale= 'totalscore'*25
if totalscore>=3.6
a=4
elsif totalscore>=0.6 and totalscore<2
a=1
elsif totalscore>=2 and totalscore<3
a=2
elsif totalscore>=3 and totalscore<3.6
a=3
else
a=0.5
endif
if totalscale>=90
s=4
elsif totalscale>=15 and totalscale<50
s=1
elsif totalscale>=50 and totalscale<75
s=2
elsif totalscale>=75 and totalscale<90
s=3
else
s=0.5
endif
#vvv=a+('totalscale'/100)
vvv=totalscore+('totalscale'/100)
if vvv>=4
u=4*(1-(randomInteger(1,16)/100))
else
u=vvv-(randomInteger(1,16)/100)
endif
if totalscore>=4
xx=30
elsif totalscore>=3.80 and totalscore<4
xx=29
elsif totalscore>=3.60 and totalscore<3.80
xx=28
elsif totalscore>=3.5 and totalscore<3.6
xx=27
elsif totalscore>=3.3 and totalscore<3.5
xx=26
elsif totalscore>=3.15 and totalscore<3.3
xx=25
elsif totalscore>=3.08 and totalscore<3.15
xx=24
elsif totalscore>=3 and totalscore<3.08
xx=23
elsif totalscore>=2.83 and totalscore<3
xx=22
elsif totalscore>=2.60 and totalscore<2.83
xx=21
elsif totalscore>=2.5 and totalscore<2.60
xx=20
elsif totalscore>=2.30 and totalscore<2.50
xx=19
elsif totalscore>=2.23 and totalscore<2.30
xx=18
elsif totalscore>=2.15 and totalscore<2.23
xx=17
elsif totalscore>=2 and totalscore<2.15
xx=16
elsif totalscore>=1.93 and totalscore<2
xx=15
elsif totalscore>=1.83 and totalscore<1.93
xx=14
elsif totalscore>=1.74 and totalscore<1.83
xx=13
elsif totalscore>=1.66 and totalscore<1.74
xx=12
elsif totalscore>=1.50 and totalscore<1.66
xx=11
elsif totalscore>=1.33 and totalscore<1.50
xx=10
else
xx=9
endif
overscore = xx*4/30
ov = overscore
if xx>=25
xxban$="C"
elsif xx>=20 and xx<25
xxban$="B2"
elsif xx>=16 and xx<20
xxban$="B1"
elsif xx>=10 and xx<16
xxban$="A2"
else
xxban$="A1"
endif
qaz = 0.18
rr = (r*4+qr*2+z*1)/7
lu = (l*1+w*2+inpro*4/125)/4
td = (w*1+o*2+inpro*1/125)/3.25
facts=(ln(7/4)*4/7+ln(7/2)*2/7+ln(7)*1/7+ln(4)*1/4+ln(2)*1/2+ln(4)*1/4+ln(3.25)*1/3.25+ln(3.25/2)*2/3.25+ln(3.25/0.25)*0.25/3.25+ln(14.25/7)*7/14.25+ln(14.25/4)*4/14.25+ln(14.25/3.35)*3.25/14.25)
totsco = (r*ln(7/4)*4/7+qr*ln(7/2)*2/7+z*ln(7)*1/7+l*ln(4)*1/4+w*ln(2)*1/2+ln(4)*1/4*inpro*4/125+w*ln(3.25)*1/3.25+o*ln(3.25/2)*2/3.25+ln(3.25/0.25)*0.25/3.25*inpro*4/125)/facts
if totalscore>=4
totsco=3.9
else
totsco=totalscore
endif
rrr = rr*qaz
lulu = lu*qaz
tdtd = td*qaz
totscoo = totsco*qaz
whx=rrr*cos(1.309)
why=rrr*sin(1.309)
who=4*qaz
probpron=(r/4)
lstd=(10*l)/4
ostd=(10*o)/4
wstd=(10*w)/4
rstd=(10*r)/4
zstd=(10*z)/4
qstd=(10*qr)/4
Erase all
appendInfoLine: "1. voicedcount = ", 'voicedcount:0'
appendInfoLine: "2. npause = ", 'npause:0'
appendInfoLine: "3. speakingrate = ", 'speakingrate:2'
appendInfoLine: "4. articulationrate = ", 'articulationrate:2'
appendInfoLine: "5. speakingtot = ", 'speakingtot:2'
appendInfoLine: "6. originaldur = ", 'originaldur:2'
appendInfoLine: "7. balance = ", 'balance:1'
appendInfoLine: "8. meanall = ", 'meanall:2'
appendInfoLine: "9. sd = ", 'sd:2'
appendInfoLine: "10. medi = ", 'medi:1'
appendInfoLine: "11. mini = ", 'mini:0'
appendInfoLine: "12. maxi = ", 'maxi:0'
appendInfoLine: "13. quantile250 = ", 'quantile250:0'
appendInfoLine: "14. quantile750 = ", 'quantile750:0'
appendInfoLine: "15. probpron = ", 'probpron:2'