Guest User

Vowel Isolation + formant analysis Praat script

a guest
Nov 14th, 2017
2,327
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.80 KB | None | 0 0
  1. #
  2. # VowelOnset.Praat
  3. #
  4. # This script runs in the Praat speech analysis program;
  5. # see www.praat.org for more details
  6. # It starts with one Sound object selected.
  7. # The purpose of the script is to find vowel onsets in the Sound,
  8. # using a procedure similar to Cummins & Port 1998 J.Phonetics
  9. #
  10. # (c) Hugo Quené, May-June 2001, <[email protected]>
  11. # with thanks to Paul Boersma for useful hints and suggestions!
  12. # Extended by /u/kayleepop 2017 to include formant analysis and an info box
  13. #
  14. # adjusted Sep 2001 for improved performance, [email protected]
  15. #
  16. # lines starting with # are comment
  17.  
  18. # make sure that a single sound is selected
  19. aantalselect = numberOfSelected ("Sound")
  20. # obsolete... getnumberofselected aantalselect Sound
  21. if 'aantalselect'!=1
  22. print Failure: exactly 1 Sound object should be selected!
  23. printline
  24. else
  25.  
  26. selectedObj = selected()
  27.  
  28. # peak must be higher than preceding trough by 'delta' in dB, to qualify as peak
  29. # disregard bottom and top 10% of intensity rise, in dB
  30.  
  31. # Dec.12th filtering adjusted
  32. # comment vowel energy may be emphasised, by filtering with C=1000, B=500 Hz
  33. # form Analysis parameters
  34. # A vowel is characterised by a peak in the intensity contour.
  35. # You can filter the speech first, before the intensity contour is calculated.
  36. # This filtering will enhance the vowel part of the spectrum.
  37. filterfirst = 1
  38. # _
  39. # A relevant peak in the intensity contour must exceed
  40. # a minimum intensity level, which is specified as the
  41. # maximum intensity level minus a `threshold`.
  42. # Intensity peaks below this minimum will be ignored.
  43. # A small value (e.g. 2) will ignore most vowel onsets; a large
  44. # value (e.g. 18) may yield spurious vowel onsets.
  45. threshold = 8
  46. # endform
  47. # comment For determining the midpoint of the rise, the bottom and top parts are ignored.
  48. # comment This focuses on the central (and often steepest) part of the rise.
  49. # comment These ignored margins are defined as the bottom and top `margin` of the rise.
  50. # positive margin_(proportion) 0.20
  51.  
  52. # obsolete ... getnameofselected geluid1 Sound 1
  53. name1$ = selected$ ("Sound")
  54. # not necessary ... getidofselected geluidid1 Sound 1
  55.  
  56. # select selected Sound... not necessary... select 'geluidid1'
  57. # copy object name to 'temp' to avoid resampling of original Sound!
  58. Copy... temp
  59.  
  60. # downsample
  61. ## check current Fs before downsampling #
  62. fs = Get sample rate
  63. if fs>11025
  64. Resample... 11025 1
  65. Rename... temp
  66. endif
  67.  
  68. finish = Get finishing time
  69.  
  70. if filterfirst
  71. # filter with CF=1000, B=600, hi-freq attentuation, vowel-freq boost
  72. # sharpen filter to discard more hi-freq components, B=500
  73. # Filter (one pole)... 1000 500
  74. # Dec.12th change of filter, for better results
  75. # 20050111 name of call has changed in Praat 4.2
  76. # De-emphasize... 50
  77. # Filter (de-emphasis)... 50
  78. Filter (one formant)... 1000 500
  79.  
  80. # added Dec.12th
  81. # the filter operation leaves a longer sound, padded with zeroes
  82. # discard these extra zeroes
  83. # see manual p.629
  84. Extract part... 0 'finish' Rectangular 1 1
  85. # this leaves an extracted sound "*_part"
  86. Rename... temp
  87. endif
  88.  
  89. # calculate intensity contour
  90. # minimum F0 is set to long time window, as suggested by PB, to avoid shimmer and AM
  91. # smooth over 80 ms time window, as suggested by Port
  92. # smooth here over 25 ms time window, also smoothing later when taking derivative
  93. framelength = 0.01
  94. # To Intensity... 12.5 'framelength'
  95. # changed for Tiffany's female voice
  96. # To Intensity... 150 'framelength'
  97. # 20050112 HQ
  98. # changed for Frank Wijnen 's male voice, min pitch across words is 74.9 Hz
  99. # but these values yield too smoothed contour
  100. # 20101202 hq adjusted to value 40, was 100, after vowelonset.3b.praat
  101. # 20101202 hq further adjusted to value 60, was 40, because
  102. # otherwise some early peaks will not be detected because of time smearing
  103. To Intensity... 60 'framelength'
  104. # 20050112 HQ
  105. # higher precision, sinc70,
  106. # 20101202 interpolation changed back to Cubic
  107. maxint = Get maximum... 0 0 Cubic
  108. t1 = Get time from frame... 1
  109.  
  110. Down to Matrix
  111. Rename... temp
  112. endtime = Get highest x
  113. ncol = Get number of columns
  114. coldist = Get column distance
  115.  
  116. # calculate derivative over window of length 2h+1
  117. # Press, Teukolsky, Vetterling & Flannery 1992 "Numerical Recipes in C" par.5.7
  118. # interval length MUST be an odd number of frames -- otherwise timing points are not correct!
  119. h=1
  120. newt1 = 't1'+('h'*'framelength')
  121. ncol = 'ncol'-(2*'h')
  122. # obtain derivative of Intensity matrix here.
  123. # note that frames are NOT aligned between temp and intdot matrices;
  124. # derivative of interval temp[col-h],temp[col+h] corresponds to temp frame 'col'
  125. # but to intdot frame 'col-h' because intdot frames "start later" and end earlier by 'h' frames ;
  126. # hence intdot frame 'col' corresponds to temp frame 'col'+h in time
  127. # so derivative is taken over interval (col+h-h,col+h+h)
  128. Create Matrix... intdot 0 'endtime' 'ncol' 'coldist' 'newt1' 1 1 1 1 1 (Matrix_temp[1,col+'h'+'h']-Matrix_temp[1,col]) / (2*'h'*dx)
  129.  
  130. # to make the above work, you have to make sure that there is no speech signal
  131. # in the initial and final portions with duration h*framelength
  132.  
  133. # convert derivative of Intensity to Sound # hack from PB
  134. To Sound (slice)... 1
  135. Rename... temp_IntDot
  136.  
  137. # select this Sound
  138. select Sound temp_IntDot
  139. # find positive extrema, maxima, in derivative of Intensity,
  140. # which correspond to steepest rises in Intensity;
  141. # typically occurring just BEFORE vowel activity in oscillogram
  142. To PointProcess (extrema)... Left yes no Sinc70
  143. Rename... temp_rises
  144.  
  145. select Sound temp_IntDot
  146. # find negative zero-crossings, or falling zero points, in deriv of Int,
  147. # which correspond to peaks in Intensity;
  148. # typically occurring at MAX vowel amplitude in oscillogram
  149. select Sound temp_IntDot
  150. To PointProcess (zeroes)... Left no yes
  151. Rename... temp_peaks
  152.  
  153. # assume that true vowel onsets actually occur between moment of steepest rise
  154. # and moment of maximum amplitude.
  155. # 'between' is initially defined as 'halfway in time' between the points.
  156.  
  157. select PointProcess temp_peaks
  158. Copy... temp_onsets
  159. Remove points between... 0 'endtime'
  160.  
  161. select PointProcess temp_peaks
  162. npeaks = Get number of points
  163. for pindex from 1 to 'npeaks'
  164. select PointProcess temp_peaks
  165. ptime = Get time from index... 'pindex'
  166. select Intensity temp
  167. pint = Get value at time... 'ptime' Nearest
  168. # relative peak intensity, local peak relative to threshold relative to maximum
  169. # relpint = pint - (maxint-threshold)
  170. if pint > (maxint-threshold)
  171. select PointProcess temp_rises
  172. # the following line leads to crashes when detecting metronome beats
  173. # rindex = Get low index... 'ptime'
  174. # because the beats may occur immediately in the file
  175. # the derivative has no positive zerocrossing BEFORE the peak
  176. # so there is no detectable RISE before the PEAK
  177. # this leads to rindex=0 which has fatal consequences furtheron.
  178. # workaround added Dec.11th:
  179. # use rtime only if rindex>0
  180. rindex = Get low index... 'ptime'
  181. if rindex>0
  182. rtime = Get time from index... 'rindex'
  183. # onsettime is halfway in time between steepest-rise-moment and peak-moment
  184. otime = ('rtime'+'ptime')/2
  185. else
  186. otime = 'ptime'
  187. endif # rindex>0
  188. select PointProcess temp_onsets
  189. Add point... 'otime'
  190. # added code Jan.18 to calculate stress score
  191. # get actual rise value from temp_IntDot
  192. # select Sound temp_IntDot
  193. # rise = Get value at time... 'rtime' Cubic
  194. # peak = pint-(maxint-threshold)
  195. # printline BINGO: time='otime' peak='peak' rise='rise'
  196. endif # pint>threshold
  197. endfor # pindex from 1 to npeaks
  198.  
  199. # cleanup
  200. select Sound temp
  201. # select Sound temp_rsm
  202. plus Intensity temp
  203. plus Matrix temp
  204. plus Matrix intdot
  205. plus Sound temp_IntDot
  206. plus PointProcess temp_rises
  207. plus PointProcess temp_peaks
  208. Remove
  209. select Sound temp
  210. Remove
  211.  
  212. # 5 lines to remove additional objects
  213. select Sound temp
  214. select Sound temp_filt
  215. Remove
  216. select Sound temp
  217. Remove
  218.  
  219.  
  220. # Below was added by /u/kayleepop
  221. #
  222. select PointProcess temp_onsets
  223. vowelStart = Get time from index: 1
  224. vowelEnd = vowelStart + 0.07
  225. Remove
  226. selectObject: selectedObj
  227. Extract part: vowelStart, vowelEnd, "rectangular", 1, "no"
  228. extracted = selected()
  229.  
  230. To Pitch... 0.0 75 600
  231. writeInfoLine: "Pitch (mean):"
  232. meanPitch = Get mean: 0, 0, "Hertz"
  233. appendInfo: " "
  234. appendInfo: fixed$ (meanPitch, 2)
  235. appendInfoLine: " Hz"
  236. Remove
  237.  
  238. selectObject: extracted
  239. To Formant (burg)... 0.0 5.0 5500.0 0.025 50.0
  240.  
  241. appendInfoLine:""
  242. appendInfoLine: "F1 (mean):"
  243. meanF1 = Get mean: 1, 0, 0, "Hertz"
  244. appendInfo: " "
  245. appendInfo: fixed$ (meanF1, 2)
  246. appendInfoLine: " Hz"
  247.  
  248. appendInfoLine:""
  249. appendInfoLine: "F2 (mean):"
  250. meanF2 = Get mean: 2, 0, 0, "Hertz"
  251. appendInfo: " "
  252. appendInfo: fixed$ (meanF2, 2)
  253. appendInfoLine: " Hz"
  254.  
  255. # remove formant object
  256. Remove
  257. selectObject: extracted
  258. Remove
Advertisement
Add Comment
Please, Sign In to add comment