Demo entry 6783339

praat

   

Submitted by anonymous on Feb 08, 2019 at 20:38
Language: Praat. Code size: 7.8 kB.

# merge vowels and perform MFCC extraction given a folder of textgrids and sound files
# June 2018
##############################################
# MERGE VOWELS
# modified from Christian DiCanio, Haskins Laboratories, 2014.
# combines adjacent vowel and Rs and removes irrelevant words


writeFile: "Boston2015-16_files.txt", ""

# READ IN FOLDER OF TEXTGRIDS
directory$ = "/Users/sarahgupta/Dropbox/MFCC/Boston2015-16_MFCC/incomplete"
folders = Create Strings as directory list: "dlist", directory$
i = Get number of strings
for fol to i
	select Strings dlist
	folder$ = Get string... fol
	curr$ = directory$ + "/'folder$'"
	strings = Create Strings as file list: "list", curr$ + "/*.TextGrid"

 
	# LOOP THROUGH LIST OF TEXTGRIDS
	num = Get number of strings
	for ifile to num
		select Strings list
		fileName$ = Get string... ifile
		Read from file... 'curr$'/'fileName$'

		tgID = selected("TextGrid")

		select tgID

		# now get the number of intervals in the phone tier
		num_labels = Get number of intervals... 1
		
		# LOOP THROUGH PHONE TIER
		for i to num_labels-3
			# get the labels for the phones
			label_p$ = Get label of interval... 1 i
			label_f$ = Get label of interval... 1 (i+1)

			label_fnext$ = Get label of interval... 1 (i+2)					
			# if the preceding is a vowel and the following is an R, combine tags label_f$ = "R"
	
			vowel$ = "^(A|E|I|O|U)(A|H|E|Y|O|U|W)(0|1)$"

			has_vowel = index_regex: label_p$, vowel$
			has_r = index_regex: label_f$, "R"

			# if the phone after the R is a vowel, we don't want it
			constraints = index_regex: label_fnext$, vowel$

			if has_vowel = 1 and has_r = 1 and constraints <> 1
				new_label_name$ = label_p$ + label_f$
				Remove right boundary: 1, i
				Set interval text: 1, i, new_label_name$
			else
				# nothing
			endif								
		
			# RECALCULATE NUMBER OF INTERVALS
			num_labels = Get number of intervals... 1

		endfor

		select tgID
		myTextGrid = selected("TextGrid")

		speaker_code$ = mid$ (fileName$, 1, 24)

		file$ = selected$("TextGrid")
		Save as text file: "'curr$'/'file$'_vowelR.TextGrid"
		######################################################################################################################################
		# EXTRACT MFCCs FOR THIS FILE
		# modified from Koops script

		# READ IN AND SELECT SOUND & TEXTGRID

		sound_name$ = speaker_code$ + ".wav"
		Read from file... 'curr$'/'sound_name$'
		mySound = selected("Sound")


		# Now create a Table to hold MFCCs and other info

		Create Table with column names... MFCC 1 speaker word token pre_segment fol_segment vowelR vowel_type time norm_time c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 
		# First we query the TextGrid to see how many segments are marked off

		select myTextGrid
		number_of_intervals = Get number of intervals... 1

		#initialize token number
		t = 1
	
		# Now we loop through the intervals (number of phones) in the TextGrid to find the vowels
		for n to number_of_intervals

			select myTextGrid
			label$ = Get label of interval... 1 n

			# CHECK THE TYPE OF THE VOWEL
			front = index_regex: label$, "^(AE|EH|EY|IH|IY)(0|1)R$"
			back = index_regex: label$, "^(AA|AO|OW|OY|UY|UW)(0|1)R$"

			if front = 1
				type$ = "front"
			elsif back = 1
				type$ = "back"
			else
				type$ = ""
			endif


			# Any interval that has a label of vowelR or ER we want to keep

			vowelr = index_regex: label$, "^(A|E|I|O|U)(A|H|E|Y|O|U|W)(0|1)R$"
			er = index_regex: label$, "ER(0|1)"

			if vowelr = 1 or er = 1
				word$ = ""

           		# if we come across a vowelR, we want to look at the word
				select myTextGrid
				beg = Get start point... 1 n
				end = Get end point... 1 n
				dur = end-beg

				# if we have a word in this tier, look into it
				# loop through the word intervals
				numWords = Get number of intervals... 2
				for intervalNumber from 1 to numWords
				
					# get the label of the interval, which is the word itself
    				text$ = Get label of interval: 2, intervalNumber
					# get the beginning and end times of the word
					beg_word = Get starting point... 2 intervalNumber
					end_word = Get end point... 2 intervalNumber
		
					# find out if there is a match b/w word and the regular expression 
					match = index_regex: text$, "^[a-z]+(a|e|i|o|u)r([^ry]+)?$"
	
					# if there's a match and the vowel is in range of the word, keep track
					if match = 1 and beg_word <= beg and end_word >=end
						word$ = text$
					endif		
				endfor

				# when we drop out of the loop, we have stored the word belonging to the vowel

    			# put the word boundary sign as previous and following
				select myTextGrid

				# if we're in bounds, we can update the previous segment
				if n>1
					pre$ = Get label of interval... 1 n-1
				endif

				# if in bounds, we can update the following segment
				if n < number_of_intervals
					fol$ = Get label of interval... 1 n+1
				endif

				if right$(word$, 2) == "er" or right$(word$, 2) == "re" or right$(word$, 2) == "ar" or fol$ == "sp"
					fol$ = "#"
				endif

			
				#  Now extract a small piece of the Soundfile (good when dealing with very large soundfiles)


				select mySound 
				Extract part... beg end rectangular 1 yes
				Rename... part

				# Create MFCC
				# decide sampling rate
				s = dur/100

				To MelSpectrogram... 0.001 s 100 100 0
    			To MFCC... 12
				To TableOfReal... include energy
		
				numRows = object["TableOfReal part"].nrow
		
				# SELECT THE MFCC OUTPUT AND PUT THESE VALUES IN TABLE
				selectObject: "TableOfReal part"
		
				# TAKE EACH VALUE FROM EACH ROW IN THE TABLE 
				for r from 1 to numRows
					c1 = object["TableOfReal part", r, 1]
					c2 = object["TableOfReal part", r, 2]
					c3 = object["TableOfReal part", r, 3]
					c4 = object["TableOfReal part", r, 4]
					c5 = object["TableOfReal part", r, 5]
					c6 = object["TableOfReal part", r, 6]
					c7 = object["TableOfReal part", r, 7]
					c8 = object["TableOfReal part", r, 8]
					c9 = object["TableOfReal part", r, 9]
					c10 = object["TableOfReal part", r, 10]
					c11 = object["TableOfReal part", r, 11]
					c12 = object["TableOfReal part", r, 12]


					# now put the values in our table and normalize for length
		
					time = beg+(r-1)*(dur/numRows)
					norm_time = (r-1)*(1/numRows)
			
					token$ = speaker_code$ + "_" + string$(t)
			
					select Table MFCC
					Append row
					row = Get number of rows
					Set string value... row speaker 'speaker_code$'
					Set string value... row word 'word$'
					Set string value... row token 'token$'
					Set string value... row vowelR 'label$'
					Set string value... row vowel_type 'type$'
					Set string value... row pre_segment 'pre$'
					Set string value... row fol_segment 'fol$'
					Set numeric value... row time 'time:4'
					Set numeric value... row norm_time 'norm_time:4'
		
					# MFCC VALUES
					Set numeric value... row c1 'c1'
					Set numeric value... row c2 'c2'
					Set numeric value... row c3 'c3'
					Set numeric value... row c4 'c4'
					Set numeric value... row c5 'c5'
					Set numeric value... row c6 'c6'
					Set numeric value... row c7 'c7'
					Set numeric value... row c8 'c8'
					Set numeric value... row c9 'c9'
					Set numeric value... row c10 'c10'
					Set numeric value... row c11 'c11'
					Set numeric value... row c12 'c12'
				endfor

				# increment token number when we move on to a new interval
				t+=1

    			# CLEAN UP
    			select Sound part
				plus MelSpectrogram part
				plus MFCC part
				plus TableOfReal part
    			Remove
			endif
		endfor

		select Table MFCC
		Remove row... 1

		# SAVE MFCC FILE AS CSV IN CORRECT FOLDER
		speaker_num$ = mid$(speaker_code$, 14, 3)
		Save as comma-separated file: "'curr$'/'file$'_MFCC.csv"
		file_name$ = file$ + "_MFCC.csv"

		appendFileLine: "Boston2015-16_files.txt", file_name$

	endfor
endfor

This snippet took 0.01 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).