Created
December 16, 2022 13:37
-
-
Save Nesh108/75a4760e60c1456ba669c2e88b9d6935 to your computer and use it in GitHub Desktop.
[Speed Processing] Processing Praat TextGrids to calculate F1, F2 and F0 of angry and sad emotion files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import glob | |
import tgt | |
import sys | |
import parselmouth | |
import statistics | |
DEBUG = False | |
def get_f0_mean_stdev(filesSounds): | |
sum = 0 | |
f0s = [] | |
for i, filename in enumerate(filesSounds): | |
pitch = parselmouth.Sound(filename).to_pitch() | |
f0_val = pitch.get_mean_absolute_slope() | |
sum += f0_val | |
f0s.append(f0_val) | |
return [sum/len(filesSounds), statistics.stdev(f0s)] | |
def process_formants(filesTextgrid, filesSound): | |
vowels_formants = { | |
"a": [[],[]], | |
"i": [[],[]], | |
"u": [[],[]], | |
} | |
for i, filename in enumerate(filesTextgrid): | |
try: | |
tg = tgt.io.read_textgrid(filename) | |
formant = parselmouth.Sound(filesSound[i]).to_formant_burg() | |
if DEBUG: | |
print(filename + " + " + filesSound[i]) | |
for tiername in tg.get_tier_names(): | |
if tiername in ["a", "i", "u"]: | |
annotation = tg.get_tier_by_name(tiername).get_annotations_with_text(tiername)[0] | |
f1_start_value = formant.get_value_at_time(1, annotation.start_time) | |
f1_end_value = formant.get_value_at_time(1, annotation.end_time) | |
f1_mean = (f1_start_value + f1_end_value) / 2 | |
f2_start_value = formant.get_value_at_time(2, annotation.start_time) | |
f2_end_value = formant.get_value_at_time(2, annotation.end_time) | |
f2_mean = (f2_start_value + f2_end_value) / 2 | |
vowels_formants[tiername][0].append(f1_mean) | |
vowels_formants[tiername][1].append(f2_mean) | |
if DEBUG: | |
print(filename + " " + format_formant(tiername, f1_mean, f2_mean)) | |
elif DEBUG: | |
print('\t Skipping: ' + tiername) | |
except err: | |
print(filename + ' caused a problem.') | |
sys.stderr.write('ERROR: %s\n' % str(err)) | |
return vowels_formants | |
def calculateFormantAverages(v_formants): | |
vowels = { | |
"a": [0,0], | |
"i": [0,0], | |
"u": [0,0], | |
} | |
for vowel_name, formants in v_formants.items(): | |
sum = 0 | |
for f0 in formants[0]: | |
sum += f0 | |
vowels[vowel_name][0] = sum / len(formants[0]) | |
sum = 0 | |
for f1 in formants[1]: | |
sum += f1 | |
vowels[vowel_name][1] = sum / len(formants[1]) | |
return vowels | |
def print_formants(formants): | |
for vowel_name, formants in formants.items(): | |
print(format_formant(vowel_name, formants[0], formants[1])) | |
def format_formant(vowel, f1, f2): | |
return "\t" + vowel + ") F1: " + str(f1) + " | F2: " + str(f2) | |
def main(argv=None): | |
print("=== Angry Emotions Analysis ===") | |
print("===============================\n") | |
filesTextgrid = glob.glob(r'../A_*.TextGrid') | |
filesSound = glob.glob(r'../wav/A_*.wav') | |
angry_formants = process_formants(filesTextgrid, filesSound) | |
print_formants(calculateFormantAverages(angry_formants)) | |
mean, stdev = get_f0_mean_stdev(filesSound) | |
print("\tF0) Mean: " + str(mean) + " | Stdev: " + str(stdev)) | |
print("\n=== Sad Emotions Analysis ===") | |
print("=============================\n") | |
filesTextgrid = glob.glob(r'../S_*.TextGrid') | |
filesSound = glob.glob(r'../wav/S_*.wav') | |
sad_formants = process_formants(filesTextgrid, filesSound) | |
print_formants(calculateFormantAverages(sad_formants)) | |
mean, stdev = get_f0_mean_stdev(filesSound) | |
print("\tF0) Mean: " + str(mean) + " | Stdev: " + str(stdev)) | |
if __name__ == '__main__': | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment