vot.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. # Author: Josh Bicking
  2. from praatio import tgio
  3. import sys
  4. from os.path import join
  5. import numpy
  6. import subprocess
  7. if len(sys.argv) != 4:
  8. print("Usage: {} FOLDER LANG TIER-NAME".format(sys.argv[0]))
  9. print("FOLDER contains the 15 annotated voice samples.")
  10. print("LANG is the language (the prefix of the sound/TextGrid files, english or russian).")
  11. print("TIER-NAME is the name of the ipa tier. Either 'ipa' or 'IPA-phones'.")
  12. exit(1)
  13. folder = sys.argv[1]
  14. langname = sys.argv[2]
  15. tiername = sys.argv[3]
  16. # list of vowels
  17. vowels = ["i","y","ɨ","ʉ","ɯ","u","ɪ","ʏ","ɪ̈","ʊ̈",
  18. "ʊ","e","ø","ɘ","ɵ","ɤ","o","e̞","ø̞",
  19. "ə","ɤ̞","o̞","ɛ","œ","ɜ","ɞ","ʌ","ɔ",
  20. "æ","ɐ","a","ɶ","ä","ɑ","ɒ"]
  21. # List of all VOTs discovered
  22. vot = {}
  23. # Open all Files
  24. lang = []
  25. russian = []
  26. for i in range(1,16):
  27. lang.append(tgio.openTextgrid(join(folder, "{}{}.TextGrid".format(langname, i))).tierDict[tiername].entryList)
  28. # Find all stop consonants with a vowel after them
  29. stop_consonants = ["t", "d", "k", "g", "p", "b", "ʔ"]
  30. for i in range(0,15):
  31. for j in range(0, len(lang[i])):
  32. if (lang[i][j].label != "" # Not silence
  33. and lang[i][j].label[0] in stop_consonants # Is a stop consonant
  34. and j + 1 < len(lang[i]) # Has an entry after it
  35. and lang[i][j+1].label != "" # Not silence either
  36. and lang[i][j+1].label[0] in vowels): # Is a vowel or dipthong
  37. # Build a script to find where pitch stops
  38. # We're estimating VOT as "the time between where the
  39. # consonant Interval of the TextGrid ends, and the
  40. # beginning of pitch (voicing) starts".
  41. start = lang[i][j].start
  42. end = lang[i][j+1].end
  43. zero = lang[i][j].end
  44. script = [
  45. 'Read from file: "{}"'.format(join(folder, '{}{}.wav'.format(langname, i+1))),
  46. 'To Pitch: 0, 75, 600']
  47. for k in numpy.arange(start, end, .001):
  48. script.append('p = Get value at time: {:.3f}, "Hertz", "Linear"'.format(k))
  49. script.append('appendInfoLine: p')
  50. script.append('')
  51. script = "\n".join(script)
  52. f = open(join(folder, "tempscript.praat"), "w")
  53. f.write(script)
  54. f.close()
  55. s = subprocess.run(["praat", join(folder, "tempscript.praat")], stdout=subprocess.PIPE)
  56. s = str(s.stdout)[2:].split("\\n")
  57. pitch_start = 0
  58. for line in s:
  59. if line == "--undefined--":
  60. pitch_start += 1
  61. else:
  62. break
  63. if not (pitch_start == 0 or pitch_start == len(s)):
  64. # Find where the pitch starts, relative to the sound file
  65. results = (start + pitch_start) - zero
  66. if lang[i][j].label[0] + lang[i][j+1].label[0] not in vot:
  67. vot[lang[i][j].label[0] + lang[i][j+1].label[0]] = []
  68. vot[lang[i][j].label[0] + lang[i][j+1].label[0]].append(str(results))
  69. for key in sorted(vot):
  70. print("{},{},{}".format(key[0], key[1], ",".join(vot[key])))