praatio.praat_scripts
Python wrappers for various praat scripts contained in /praatScripts.
see examples/auto_segment_speech.py, examples/get_pitch_and_formants.py, klatt_resynthesis.py
1""" 2Python wrappers for various praat scripts contained in /praatScripts. 3 4see **examples/auto_segment_speech.py**, **examples/get_pitch_and_formants.py**, 5**klatt_resynthesis.py** 6""" 7 8import os 9from os.path import join 10import io 11import csv 12from typing import List, Optional, Tuple 13 14from praatio import audio 15from praatio import data_points 16from praatio.utilities import constants 17from praatio.utilities import utils 18 19SILENCE_LABEL = "silent" 20SOUND_LABEL = "sound" 21 22 23def changeGender( 24 praatEXE: str, 25 wavFN: str, 26 outputWavFN: str, 27 pitchFloor: float, 28 pitchCeiling: float, 29 formantShiftRatio: float, 30 pitchMedian: float = 0.0, 31 pitchRange: float = 1.0, 32 duration: float = 1.0, 33 scriptFN: Optional[str] = None, 34) -> None: 35 """Changes the speech formants in a file using praat's change gender function 36 37 PitchMedian = 0.0; no change in median pitch 38 PitchRange = 1.0; no change in pitch range 39 40 Uses the following praat command: 41 https://www.fon.hum.uva.nl/praat/manual/Sound__Change_gender___.html 42 """ 43 if scriptFN is None: 44 scriptFN = join(utils.scriptsPath, "change_gender.praat") 45 46 # Praat crashes on exit after resynthesis with a klattgrid 47 utils.runPraatScript( 48 praatEXE, 49 scriptFN, 50 [ 51 wavFN, 52 outputWavFN, 53 pitchFloor, 54 pitchCeiling, 55 formantShiftRatio, 56 pitchMedian, 57 pitchRange, 58 duration, 59 ], 60 ) 61 62 63def changeIntensity( 64 praatEXE: str, 65 wavFN: str, 66 outputWavFN: str, 67 newIntensity: float, 68 scriptFN: Optional[str] = None, 69) -> None: 70 """Changes the intensity of the wavFN (in db) 71 72 Uses the following praat command: 73 https://www.fon.hum.uva.nl/praat/manual/Sound__Scale_intensity___.html 74 """ 75 if scriptFN is None: 76 scriptFN = join(utils.scriptsPath, "change_intensity.praat") 77 78 # Praat crashes on exit after resynthesis with a klattgrid 79 utils.runPraatScript(praatEXE, scriptFN, [wavFN, outputWavFN, newIntensity]) 80 81 82def getFormants( 83 praatEXE: str, 84 inputWavFN: str, 85 outputTxtFN: str, 86 maxFormant: float, 87 stepSize: float = 0.01, 88 window_length: float = 0.025, 89 preemphasis: float = 50, 90 scriptFN: Optional[str] = None, 91 undefinedValue: Optional[str] = None, 92) -> List: 93 """Get F1, F2, and F3 for the audio file 94 95 maxFormant = 5500 for females, 5000 for males, <8000 for children 96 97 Uses the following praat command: 98 https://www.fon.hum.uva.nl/praat/manual/Sound__To_Formant__burg____.html 99 """ 100 if scriptFN is None: 101 scriptFN = join(utils.scriptsPath, "get_formants.praat") 102 103 argList = [ 104 inputWavFN, 105 outputTxtFN, 106 stepSize, 107 maxFormant, 108 window_length, 109 preemphasis, 110 -1, 111 -1, 112 ] 113 utils.runPraatScript(praatEXE, scriptFN, argList) 114 115 # Load the output 116 path, fn = os.path.split(outputTxtFN) 117 with open(os.path.join(path, fn), "r", encoding="utf-8") as fd: 118 csvFile = csv.reader(fd) 119 dataList = [row for row in csvFile] 120 121 # The new praat script includes a header 122 if dataList[0][0] == "time": 123 dataList = dataList[1:] 124 125 # Handle undefined values, convert values to float 126 returnList = [] 127 for row in dataList: 128 keep = True 129 for i in range(1, 4): 130 if "--" in row[i]: 131 if undefinedValue is not None: 132 row[i] = undefinedValue 133 else: 134 keep = False 135 break 136 137 if keep is True: 138 returnList.append([float(val) for val in row]) 139 140 return returnList 141 142 143def getPulses( 144 praatEXE: str, 145 inputWavFN: str, 146 outputPointTierFN: str, 147 minPitch: float, 148 maxPitch: float, 149 scriptFN: Optional[str] = None, 150) -> data_points.PointObject1D: 151 """Gets the pitch/glottal pulses for an audio file. 152 153 Uses the following praat command: 154 http://www.fon.hum.uva.nl/praat/manual/Sound___Pitch__To_PointProcess__peaks____.html 155 """ 156 if scriptFN is None: 157 scriptFN = join(utils.scriptsPath, "get_pulses.praat") 158 159 argList = [inputWavFN, outputPointTierFN, minPitch, maxPitch] 160 utils.runPraatScript(praatEXE, scriptFN, argList) 161 162 # Load the output 163 pointObj = data_points.open1DPointObject(outputPointTierFN) 164 165 return pointObj 166 167 168def getSpectralInfo( 169 praatEXE: str, 170 inputWavFN: str, 171 inputTGFN: str, 172 outputCSVFN: str, 173 tierName: str, 174 spectralPower: int = 2, 175 spectralMoment: int = 3, 176 scriptFN: Optional[str] = None, 177) -> Tuple[List, List]: 178 """Extracts various spectral measures from an audio file 179 180 Measures include: center_of_gravity, standard_deviation 181 skewness, kertosis, central_movement 182 183 Uses the following praat command: 184 http://www.fon.hum.uva.nl/praat/manual/Spectrum.html 185 """ 186 if scriptFN is None: 187 scriptFN = join(utils.scriptsPath, "get_spectral_info.praat") 188 189 argList = [ 190 inputWavFN, 191 inputTGFN, 192 outputCSVFN, 193 tierName, 194 spectralPower, 195 spectralMoment, 196 ] 197 utils.runPraatScript(praatEXE, scriptFN, argList) 198 199 # Load the output 200 with io.open(outputCSVFN, "r", encoding="utf-8") as fd: 201 data = fd.read() 202 203 dataList = data.rstrip().split("\n") 204 dataListOfLists = [row.split(",") for row in dataList] 205 titleRow, mainDataListOfLists = dataListOfLists[0], dataListOfLists[1:] 206 207 return titleRow, mainDataListOfLists 208 209 210def resynthesizePitch( 211 praatEXE: str, 212 inputWavFN: str, 213 pitchFN: str, 214 outputWavFN: str, 215 minPitch: float, 216 maxPitch: float, 217 scriptFN: Optional[str] = None, 218 pointList: Optional[List] = None, 219) -> None: 220 """Resynthesizes the pitch in a wav file with the given pitch contour file 221 222 The pitch track to use can optionally be passed in as pointList. If 223 so, it will be saved as pitchFN for praat to be able to use. 224 225 Uses the following praat command: 226 https://www.fon.hum.uva.nl/praat/manual/Manipulation.html 227 """ 228 if scriptFN is None: 229 scriptFN = join(utils.scriptsPath, "resynthesize_pitch.praat") 230 231 if pointList is not None: 232 dur = audio.QueryWav(inputWavFN).duration 233 pointObj = data_points.PointObject2D( 234 pointList, constants.DataPointTypes.PITCH, 0, dur 235 ) 236 pointObj.save(pitchFN) 237 238 utils.runPraatScript( 239 praatEXE, scriptFN, [inputWavFN, pitchFN, outputWavFN, minPitch, maxPitch] 240 ) 241 242 243def resynthesizeDuration( 244 praatEXE: str, 245 inputWavFN: str, 246 durationTierFN: str, 247 outputWavFN: str, 248 minPitch: float, 249 maxPitch: float, 250 scriptFN: Optional[str] = None, 251) -> None: 252 """Resynthesizes the duration in a wav file with the given duration tier 253 254 Uses the following praat command: 255 https://www.fon.hum.uva.nl/praat/manual/Manipulation.html 256 """ 257 if scriptFN is None: 258 scriptFN = join(utils.scriptsPath, "resynthesize_duration.praat") 259 260 utils.runPraatScript( 261 praatEXE, 262 scriptFN, 263 [inputWavFN, durationTierFN, outputWavFN, minPitch, maxPitch], 264 ) 265 266 267def annotateSilences( 268 praatEXE: str, 269 inputWavPath: str, 270 outputTGPath: str, 271 minPitch: float = 100, 272 timeStep: float = 0.0, 273 silenceThreshold: float = -25.0, 274 minSilDur: float = 0.1, 275 minSoundDur: float = 0.1, 276 silentLabel: str = SILENCE_LABEL, 277 soundLabel: str = SOUND_LABEL, 278 scriptFN: Optional[str] = None, 279) -> None: 280 """Marks the silences and non-silences of an audio file 281 282 Uses the praat command: 283 https://www.fon.hum.uva.nl/praat/manual/Sound__To_TextGrid__silences____.html 284 """ 285 if scriptFN is None: 286 scriptFN = join(utils.scriptsPath, "annotate_silences.praat") 287 288 utils.runPraatScript( 289 praatEXE, 290 scriptFN, 291 [ 292 inputWavPath, 293 outputTGPath, 294 minPitch, 295 timeStep, 296 silenceThreshold, 297 minSilDur, 298 minSoundDur, 299 silentLabel, 300 soundLabel, 301 ], 302 )
24def changeGender( 25 praatEXE: str, 26 wavFN: str, 27 outputWavFN: str, 28 pitchFloor: float, 29 pitchCeiling: float, 30 formantShiftRatio: float, 31 pitchMedian: float = 0.0, 32 pitchRange: float = 1.0, 33 duration: float = 1.0, 34 scriptFN: Optional[str] = None, 35) -> None: 36 """Changes the speech formants in a file using praat's change gender function 37 38 PitchMedian = 0.0; no change in median pitch 39 PitchRange = 1.0; no change in pitch range 40 41 Uses the following praat command: 42 https://www.fon.hum.uva.nl/praat/manual/Sound__Change_gender___.html 43 """ 44 if scriptFN is None: 45 scriptFN = join(utils.scriptsPath, "change_gender.praat") 46 47 # Praat crashes on exit after resynthesis with a klattgrid 48 utils.runPraatScript( 49 praatEXE, 50 scriptFN, 51 [ 52 wavFN, 53 outputWavFN, 54 pitchFloor, 55 pitchCeiling, 56 formantShiftRatio, 57 pitchMedian, 58 pitchRange, 59 duration, 60 ], 61 )
Changes the speech formants in a file using praat's change gender function
PitchMedian = 0.0; no change in median pitch PitchRange = 1.0; no change in pitch range
Uses the following praat command: https://www.fon.hum.uva.nl/praat/manual/Sound__Change_gender___.html
64def changeIntensity( 65 praatEXE: str, 66 wavFN: str, 67 outputWavFN: str, 68 newIntensity: float, 69 scriptFN: Optional[str] = None, 70) -> None: 71 """Changes the intensity of the wavFN (in db) 72 73 Uses the following praat command: 74 https://www.fon.hum.uva.nl/praat/manual/Sound__Scale_intensity___.html 75 """ 76 if scriptFN is None: 77 scriptFN = join(utils.scriptsPath, "change_intensity.praat") 78 79 # Praat crashes on exit after resynthesis with a klattgrid 80 utils.runPraatScript(praatEXE, scriptFN, [wavFN, outputWavFN, newIntensity])
Changes the intensity of the wavFN (in db)
Uses the following praat command: https://www.fon.hum.uva.nl/praat/manual/Sound__Scale_intensity___.html
83def getFormants( 84 praatEXE: str, 85 inputWavFN: str, 86 outputTxtFN: str, 87 maxFormant: float, 88 stepSize: float = 0.01, 89 window_length: float = 0.025, 90 preemphasis: float = 50, 91 scriptFN: Optional[str] = None, 92 undefinedValue: Optional[str] = None, 93) -> List: 94 """Get F1, F2, and F3 for the audio file 95 96 maxFormant = 5500 for females, 5000 for males, <8000 for children 97 98 Uses the following praat command: 99 https://www.fon.hum.uva.nl/praat/manual/Sound__To_Formant__burg____.html 100 """ 101 if scriptFN is None: 102 scriptFN = join(utils.scriptsPath, "get_formants.praat") 103 104 argList = [ 105 inputWavFN, 106 outputTxtFN, 107 stepSize, 108 maxFormant, 109 window_length, 110 preemphasis, 111 -1, 112 -1, 113 ] 114 utils.runPraatScript(praatEXE, scriptFN, argList) 115 116 # Load the output 117 path, fn = os.path.split(outputTxtFN) 118 with open(os.path.join(path, fn), "r", encoding="utf-8") as fd: 119 csvFile = csv.reader(fd) 120 dataList = [row for row in csvFile] 121 122 # The new praat script includes a header 123 if dataList[0][0] == "time": 124 dataList = dataList[1:] 125 126 # Handle undefined values, convert values to float 127 returnList = [] 128 for row in dataList: 129 keep = True 130 for i in range(1, 4): 131 if "--" in row[i]: 132 if undefinedValue is not None: 133 row[i] = undefinedValue 134 else: 135 keep = False 136 break 137 138 if keep is True: 139 returnList.append([float(val) for val in row]) 140 141 return returnList
Get F1, F2, and F3 for the audio file
maxFormant = 5500 for females, 5000 for males, <8000 for children
Uses the following praat command: https://www.fon.hum.uva.nl/praat/manual/Sound__To_Formant__burg____.html
144def getPulses( 145 praatEXE: str, 146 inputWavFN: str, 147 outputPointTierFN: str, 148 minPitch: float, 149 maxPitch: float, 150 scriptFN: Optional[str] = None, 151) -> data_points.PointObject1D: 152 """Gets the pitch/glottal pulses for an audio file. 153 154 Uses the following praat command: 155 http://www.fon.hum.uva.nl/praat/manual/Sound___Pitch__To_PointProcess__peaks____.html 156 """ 157 if scriptFN is None: 158 scriptFN = join(utils.scriptsPath, "get_pulses.praat") 159 160 argList = [inputWavFN, outputPointTierFN, minPitch, maxPitch] 161 utils.runPraatScript(praatEXE, scriptFN, argList) 162 163 # Load the output 164 pointObj = data_points.open1DPointObject(outputPointTierFN) 165 166 return pointObj
Gets the pitch/glottal pulses for an audio file.
Uses the following praat command: http://www.fon.hum.uva.nl/praat/manual/Sound___Pitch__To_PointProcess__peaks____.html
169def getSpectralInfo( 170 praatEXE: str, 171 inputWavFN: str, 172 inputTGFN: str, 173 outputCSVFN: str, 174 tierName: str, 175 spectralPower: int = 2, 176 spectralMoment: int = 3, 177 scriptFN: Optional[str] = None, 178) -> Tuple[List, List]: 179 """Extracts various spectral measures from an audio file 180 181 Measures include: center_of_gravity, standard_deviation 182 skewness, kertosis, central_movement 183 184 Uses the following praat command: 185 http://www.fon.hum.uva.nl/praat/manual/Spectrum.html 186 """ 187 if scriptFN is None: 188 scriptFN = join(utils.scriptsPath, "get_spectral_info.praat") 189 190 argList = [ 191 inputWavFN, 192 inputTGFN, 193 outputCSVFN, 194 tierName, 195 spectralPower, 196 spectralMoment, 197 ] 198 utils.runPraatScript(praatEXE, scriptFN, argList) 199 200 # Load the output 201 with io.open(outputCSVFN, "r", encoding="utf-8") as fd: 202 data = fd.read() 203 204 dataList = data.rstrip().split("\n") 205 dataListOfLists = [row.split(",") for row in dataList] 206 titleRow, mainDataListOfLists = dataListOfLists[0], dataListOfLists[1:] 207 208 return titleRow, mainDataListOfLists
Extracts various spectral measures from an audio file
Measures include: center_of_gravity, standard_deviation skewness, kertosis, central_movement
Uses the following praat command: http://www.fon.hum.uva.nl/praat/manual/Spectrum.html
211def resynthesizePitch( 212 praatEXE: str, 213 inputWavFN: str, 214 pitchFN: str, 215 outputWavFN: str, 216 minPitch: float, 217 maxPitch: float, 218 scriptFN: Optional[str] = None, 219 pointList: Optional[List] = None, 220) -> None: 221 """Resynthesizes the pitch in a wav file with the given pitch contour file 222 223 The pitch track to use can optionally be passed in as pointList. If 224 so, it will be saved as pitchFN for praat to be able to use. 225 226 Uses the following praat command: 227 https://www.fon.hum.uva.nl/praat/manual/Manipulation.html 228 """ 229 if scriptFN is None: 230 scriptFN = join(utils.scriptsPath, "resynthesize_pitch.praat") 231 232 if pointList is not None: 233 dur = audio.QueryWav(inputWavFN).duration 234 pointObj = data_points.PointObject2D( 235 pointList, constants.DataPointTypes.PITCH, 0, dur 236 ) 237 pointObj.save(pitchFN) 238 239 utils.runPraatScript( 240 praatEXE, scriptFN, [inputWavFN, pitchFN, outputWavFN, minPitch, maxPitch] 241 )
Resynthesizes the pitch in a wav file with the given pitch contour file
The pitch track to use can optionally be passed in as pointList. If so, it will be saved as pitchFN for praat to be able to use.
Uses the following praat command: https://www.fon.hum.uva.nl/praat/manual/Manipulation.html
244def resynthesizeDuration( 245 praatEXE: str, 246 inputWavFN: str, 247 durationTierFN: str, 248 outputWavFN: str, 249 minPitch: float, 250 maxPitch: float, 251 scriptFN: Optional[str] = None, 252) -> None: 253 """Resynthesizes the duration in a wav file with the given duration tier 254 255 Uses the following praat command: 256 https://www.fon.hum.uva.nl/praat/manual/Manipulation.html 257 """ 258 if scriptFN is None: 259 scriptFN = join(utils.scriptsPath, "resynthesize_duration.praat") 260 261 utils.runPraatScript( 262 praatEXE, 263 scriptFN, 264 [inputWavFN, durationTierFN, outputWavFN, minPitch, maxPitch], 265 )
Resynthesizes the duration in a wav file with the given duration tier
Uses the following praat command: https://www.fon.hum.uva.nl/praat/manual/Manipulation.html
268def annotateSilences( 269 praatEXE: str, 270 inputWavPath: str, 271 outputTGPath: str, 272 minPitch: float = 100, 273 timeStep: float = 0.0, 274 silenceThreshold: float = -25.0, 275 minSilDur: float = 0.1, 276 minSoundDur: float = 0.1, 277 silentLabel: str = SILENCE_LABEL, 278 soundLabel: str = SOUND_LABEL, 279 scriptFN: Optional[str] = None, 280) -> None: 281 """Marks the silences and non-silences of an audio file 282 283 Uses the praat command: 284 https://www.fon.hum.uva.nl/praat/manual/Sound__To_TextGrid__silences____.html 285 """ 286 if scriptFN is None: 287 scriptFN = join(utils.scriptsPath, "annotate_silences.praat") 288 289 utils.runPraatScript( 290 praatEXE, 291 scriptFN, 292 [ 293 inputWavPath, 294 outputTGPath, 295 minPitch, 296 timeStep, 297 silenceThreshold, 298 minSilDur, 299 minSoundDur, 300 silentLabel, 301 soundLabel, 302 ], 303 )
Marks the silences and non-silences of an audio file
Uses the praat command: https://www.fon.hum.uva.nl/praat/manual/Sound__To_TextGrid__silences____.html