## # This script opens all sound files in a directory and their associated TextGrids, # (see 'File_handling.praat' if you wish to use only single files) # measures the first 'n' formants at the midpoints of all segments that have a name # and writes the results together with the durations of these segment to the # text file "formant_center_results.txt" at the same directory of the sound file. # # This script is not very efficient, since it computes the formants for the whole files and looks only # then at the middle of the labeled segments - it would be usually much more efficient to compute # the formants only around the middle of the segments. # # ! Attention ! Praat first downsamples files to twice the frequency given in the 'Formant (burg)...' command. # For a long recording, this can take considerable time and memory and it might be much more # efficient if you downsample the file first with a 'Convert -> Resample' command to this frequency # (e.g. to 11000 Hz if you want to compute formants up to 5500 Hz). -- This is recommended especially # if you have to compute the formants over and over again for the same files. # # Version 1.0, Henning Reetz, 25-jun-2007 # Version 1.1, Henning Reetz, 18-jun-2009; skip intervals that are to short; select tier number # # Tested with Praat 5.1.07 ## # first clear the information window to have all messages in it only related to this script clearinfo ## 1) Inquire some parameters # ! Note that 'form' may only be used once in a script! form Formant parameters: comment Leave the directory path empty if you want to use the current directory. word directory comment Which tier should be analyzed? integer tier 1 comment ______________________________________________________________________________________________________________ integer max_freq 5500 integer nr_formants 5 real step_rate 0.005 real window_length 0.025 integer pre_emphasis 50 comment ______________________________________________________________________________________________________________ boolean smooth 1 endform ## 2) delete any pre-existing result file and write a header line result_file$ = directory$+"formant_center_results.txt" filedelete 'result_file$' fileappend 'result_file$' File'tab$'Label'tab$'Center[s]'tab$'Duration[ms] for i_formant to nr_formants fileappend 'result_file$' 'tab$'F'i_formant:0' endfor fileappend 'result_file$' 'newline$' # 3) Get file names from a directory # We assume here that it is more likely that a '.TextGrid' file exists if there is a sound file # (whereas sound files often exist without a '.TextGrid' file) Create Strings as file list... file_list 'directory$'*.TextGrid number_of_files = Get number of strings for i_file to number_of_files select Strings file_list grid_file_name$ = Get string... i_file Read from file... 'directory$''grid_file_name$' base_name$ = selected$("TextGrid") print Handling 'base_name$' # try to open .wav and .nsp files for this TextGrid ext1$ = ".wav" sound_file_name$ = directory$+base_name$+ext1$ if not fileReadable (sound_file_name$) ext2$ = ".nsp" sound_file_name$ = directory$+base_name$+ext2$ endif # if any of the above attempts to open a file worked, this will work as well if fileReadable (sound_file_name$) # next line not really necessary - just to prevent errors if we cut-n-paste this part into another script where things might be different select TextGrid 'base_name$' tier_one_is_interval = Is interval tier... tier if tier_one_is_interval = 1 # read in the sound file Read from file... 'sound_file_name$' # Compute the formants of the selected sound. To Formant (burg)... step_rate nr_formants max_freq window_length pre_emphasis # Use the TextGrid to find all labeled segments select TextGrid 'base_name$' nr_segments = Get number of intervals... tier for i to nr_segments select TextGrid 'base_name$' interval_label$ = Get label of interval... tier i if interval_label$ <> "" # Compute the formants at the center and +/- one step_rate around it and perform a median smoothing. begin_segment = Get starting point... tier i end_segment = Get end point... tier i t_middle = (begin_segment + end_segment) / 2 t_left = t_middle - step_rate t_right = t_middle + step_rate duration = (end_segment - begin_segment) * 1000 sec_duration = end_segment - begin_segment # check whether the interval is long enough to fits into the width of the effective window length of the analysis window if (sec_duration > window_length) fileappend 'result_file$' 'base_name$''tab$''interval_label$''tab$''t_middle:4''tab$''duration:3' select Formant 'base_name$' for i_formant to nr_formants f_middle = Get value at time... i_formant t_middle Hertz Linear # perform smoothing if required (get left/right data first) if smooth = 1 f_left = Get value at time... i_formant t_left Hertz Linear f_right = Get value at time... i_formant t_right Hertz Linear call MedianSmooth f_left f_middle f_right endif if f_middle <> undefined fileappend 'result_file$' 'tab$''f_middle:0' else fileappend 'result_file$' 'tab$'. endif endfor fileappend 'result_file$' 'newline$' else # interval is too short to be reported # un-comment lines to report short segments as well ! fileappend 'result_file$' 'base_name$''tab$''interval_label$''tab$''t_middle:4''tab$''duration:3' ! for i_formant to nr_formants ! fileappend 'result_file$' 'tab$'. ! endfor ! fileappend 'result_file$' 'newline$' endif # interval is too short test endif # interval has a label endfor # going thru all intervals # clean up select Sound 'base_name$' plus Formant 'base_name$' Remove printline finished. else # selected tier is not an interval tier print 'newline$' Tier 'tier' of 'base_name$'.TextGrid is not an interval tier. File ignored. 'newline$' endif # test whether tier is an interval tier # clean up select TextGrid 'base_name$' Remove else # no '.wav' of '.nsp' file found printline failed! No sound file 'directory$''base_name$''ext1$' or *'ext2$' found. <*** Remove endif # test for readable sound file endfor # going thru all '.TextGrid' files # clean up and inform user select Strings file_list Remove printline Done. printline Formant data written to 'result_file$'. # Procedure to perform a median smoothing on three values (i.e. pick the middle value of three) # Note this procedure is not fully save - if all three values are 'jumpy' it just picks the middle one, # which might be completely wrong; the same is true if there are only two or values and the third is # 'undefined'. In that case, the middle one is chosen (even if the two others are close to each other). # It seems to make better to include some sort of frequency limit (like 100 Hz or less than 5% of # the mean) to depart values from each other, or so. # # The procedure looks somewhat complicated but is actually checking all possibilities of which value is larger than what procedure MedianSmooth left mid right if (left <> undefined) and (mid <> undefined) and (right <> undefined) if mid > left if mid > right if left < right mid = right else mid = left endif endif else if left < right mid = left else if mid < right mid = right endif endif endif endif endproc