Difference between revisions of "Meas formants"
From Phonlab
Jump to navigationJump to searchm |
m |
||
Line 1: | Line 1: | ||
− | < |
+ | <code>meas_formants</code> is a sample script for doing formant analysis on an audio file, reading an associated Praat TextGrid, and extracting formant measurements from vowel tokens. You can copy the script and customize it to your own project. |
<nowiki> |
<nowiki> |
Revision as of 10:10, 11 February 2014
meas_formants
is a sample script for doing formant analysis on an audio file, reading an associated Praat TextGrid, and extracting formant measurements from vowel tokens. You can copy the script and customize it to your own project.
#!/usr/bin/env python # Measure formants. Read input textgrids, call ifcformant on associated audio file, # and output measurements to .meas files. Usage = 'meas_formants speaker file1.TextGrid [file2.TextGrid] ... [fileN.TextGrid]' import audiolabel import os, sys, subprocess import re import numpy as np # Do minimal checking to ensure the script was called with appropriate # arguments. try: if not (sys.argv[1] == 'male' or sys.argv[1] == 'female' or sys.argv[1] == 'child'): raise sys.argv[2] != None except: raise Exception('Usage: ' + Usage) # Regular expression used to identify vowels. vre = re.compile( "^(?P<vowel>AA|AE|AH|AO|AW|AXR|AX|AY|EH|ER|EY|IH|IX|IY|OW|OY|UH|UW|UX)(?P<stress>\d)?$" ) # Mapping of column headings to column formats fldmap = ( "t1", "0.4f", "t2", "0.4f", "lintime", "0.4f", "ifctime", "0.4f", "idx", "d", "vowel", "s", "stress", "s", "rms", "s", "f1", "s", "f2", "s", "f3", "s", "f4", "s", "f0", "s", "word", "s", "context", "s", ) # The output header line. head = '\t'.join(fldmap[0:len(fldmap):2]) + '\n' # Format string used for output. fmt = '\t'.join( \ [ \ '{' + '{0}:{1}'.format(col,fmt) + '}' \ for col, fmt in zip( \ fldmap[0:len(fldmap):2], \ fldmap[1:len(fldmap):2] \ ) \ ] \ ) + '\n' # Name to use for ifcformant output file. tempifc = '__temp.ifc' speaker = sys.argv[1] ifc_args = ['ifcformant', '--speaker=' + speaker, '-e', 'gain -n -3 sinc -t 10 60 contrast', '--print-header', '--output=' + tempifc] # Loop over all the input files specified on the command line. for tg in sys.argv[2:]: fname = os.path.splitext(tg)[0] # get filename without extension with open(fname + '.meas', 'w') as out: # Praat LabelManager. pm = audiolabel.LabelManager(fromFile=tg, fromType='praat') # Create ifcformant results and read into ifc LabelManager. proc = subprocess.Popen(ifc_args + [fname + '.wav'], stderr=subprocess.PIPE) proc.wait() if proc.returncode != 0: for line in proc.stderr: sys.stderr.write(line + '\n') raise Exception("ifcformant exited with status: {0}".format(proc.returncode)) ifc = audiolabel.LabelManager(fromFile=tempifc, fromType='table', t1Col='sec') out.write(head) # Loop over all the vowel labels in the tier named 'phone'. for v, m in pm.tier('phone').search(vre, returnMatch=True): if v.duration() > 1 and v.t1() != 0: continue # Safer to use center of a label as reference point than an edge. word = pm.tier('word').labelAt(v.center()) context = pm.tier('context').labelAt(v.center()) # Take measurements at start and end of vowel and at five # equally-spaced intervals in between them. for idx, t in enumerate(np.linspace(v.t1(), v.t2(), num=7)): meas = ifc.labelsAt(t) out.write(fmt.format(t1=v.t1(), t2=v.t2(), lintime=t, ifctime=meas.f1.t1(), idx=idx, vowel=m.group('vowel'), stress=m.group('stress'), rms=meas.rms.text, f1=meas.f1.text, f2=meas.f2.text, f3=meas.f3.text, f4=meas.f4.text, f0=meas.f0.text, word=word.text, context=context.text) ) os.unlink(tempifc)