From 402402f94ff8ccb5474177fdb56a1457f03322fd Mon Sep 17 00:00:00 2001 From: Rob van Son Date: Tue, 21 Apr 2015 16:24:44 +0200 Subject: [PATCH] First attempt to improve third tone recognition with breaking third tone pitch contours --- ToneProt/ToneRecognition.praat | 2 ++ ToneProt/ToneRules.praat | 53 +++++++++++++++++++++++++++++++++++++++ ToneProt/ToneScript.praat | 56 +++++++++++++++++++++++++++++++----------- sgc2.praat | 47 +++++++++++++++++++---------------- 4 files changed, 122 insertions(+), 36 deletions(-) diff --git a/ToneProt/ToneRecognition.praat b/ToneProt/ToneRecognition.praat index 60f9863..1323e0a 100644 --- a/ToneProt/ToneRecognition.praat +++ b/ToneProt/ToneRecognition.praat @@ -66,6 +66,8 @@ procedure FreeToneRecognition .pinyin$ .test_word$ .exclude$ .upperRegister .fre for .i from 1 to .listLength select Table ToneList .inFile$ = Get value... '.i' Word + # Broken third tones are still third tones + .inFile$ = replace$(.inFile$, "9", "3", 0) if (.exclude$ = "" or rindex_regex(.inFile$, .exclude$) <= 0) and rindex_regex(.inFile$, "[\d]") > 0 referenceName$ = .inFile$ diff --git a/ToneProt/ToneRules.praat b/ToneProt/ToneRules.praat index 0713c1d..c9c904c 100644 --- a/ToneProt/ToneRules.praat +++ b/ToneProt/ToneRules.praat @@ -169,6 +169,59 @@ procedure toneRules # Return in 1/6th of the duration toneScript.point = toneScript.point + (toneScript.voicedDuration)*1/6 Add point... 'toneScript.point' 'toneScript.endPoint' + # Third tone with voice break + elsif toneScript.toneSyllable = 9 + # Halfway the range + toneRules.startPoint = toneRules.levelThree + toneRules.lowestPoint = toneRules.levelOne * toneScript.threeSemit + # Protect pitch against "underflow" + if toneRules.lowestPoint < toneScript.absoluteMinimum + toneRules.lowestPoint = toneScript.absoluteMinimum + endif + # First syllable + if toneScript.nextTone < 0 + toneScript.endPoint = toneRules.startPoint + # Anticipate rise in next tone + elsif toneScript.nextTone = 1 or toneScript.nextTone = 4 + toneRules.lowestPoint = toneRules.levelOne / toneScript.twoSemit + toneScript.endPoint = toneRules.startPoint + # Anticipate rise in next tone and stay low + elsif toneScript.nextTone = 2 + toneRules.lowestPoint = toneRules.levelOne / toneScript.twoSemit + toneScript.endPoint = toneRules.lowestPoint + # Last one was low, don't go so much lower + elsif toneScript.prevTone = 4 + toneRules.lowestPoint = toneRules.levelOne * toneScript.oneSemit + # Anticipate rise in next tone and stay low + elsif toneScript.nextTone = 0 + toneRules.lowestPoint = toneRules.levelOne + toneScript.endPoint = toneRules.lowestPoint / toneScript.sixSemit + else + toneScript.endPoint = toneRules.startPoint + endif + + # Write toneScript.points + Add point... 'toneScript.point' 'toneRules.startPoint' + # Go 1/3 of the duration down + toneScript.point = toneScript.point + (toneScript.voicedDuration)*2/6 + Add point... 'toneScript.point' 'toneRules.lowestPoint' + + # voiceless break + .delta = 'toneScript.point' + 0.001 + Add point... '.delta' 0 + + # Go half the duration low + toneScript.point = toneScript.point + (toneScript.voicedDuration)*3/6 + + # voiceless break + .delta = 'toneScript.point' - 0.001 + Add point... '.delta' 0 + + Add point... 'toneScript.point' 'toneRules.lowestPoint' + # Return in 1/6th of the duration + toneScript.point = toneScript.point + (toneScript.voicedDuration)*1/6 + # Go on + Add point... 'toneScript.point' 'toneScript.endPoint' # Fourth tone elsif toneScript.toneSyllable = 4 # Start higher than tone 1 (by 2 semitones) diff --git a/ToneProt/ToneScript.praat b/ToneProt/ToneScript.praat index 3c3276b..44d0af1 100644 --- a/ToneProt/ToneScript.praat +++ b/ToneProt/ToneScript.praat @@ -153,28 +153,54 @@ procedure toneScript toneScript.inputWord$ toneScript.upperRegister toneScript.r endfor # 6,6 - toneScript.first = 6 - toneScript.currentWord$ = replace_regex$(toneScript.inputWord$, "^('.skipSyll$')([^\d]+)([\d]+)(.*)$", "\1\3'toneScript.first'\5", 1) - toneScript.second = 6 - if toneScript.syllableCount > 1 - toneScript.currentWord$ = replace_regex$(toneScript.currentWord$, "^('.skipSyll$')([^\d]+)([\d]+)([^\d]+)([\d]+)(.*)$", "\1\3'toneScript.first'\5'toneScript.second'\7", 1) - # Write name in list - toneScript.wordNumber = toneScript.wordNumber+1 + #toneScript.first = 6 + #toneScript.currentWord$ = replace_regex$(toneScript.inputWord$, "^('.skipSyll$')([^\d]+)([\d]+)(.*)$", "\1\3'toneScript.first'\5", 1) + #toneScript.second = 6 + #if toneScript.syllableCount > 1 + # toneScript.currentWord$ = replace_regex$(toneScript.currentWord$, "^('.skipSyll$')([^\d]+)([\d]+)([^\d]+)([\d]+)(.*)$", "\1\3'toneScript.first'\5'toneScript.second'\7", 1) + # # Write name in list + # toneScript.wordNumber = toneScript.wordNumber+1 + # if toneScript.createToneList = 1 + # select Table ToneList + # toneScript.listLength = Get number of rows + # toneScript.listLength = toneScript.listLength + 1 + # for toneScript.currLength from toneScript.listLength to toneScript.wordNumber + # Append row + # Set string value... 'toneScript.currLength' Word ------EMPTY + # endfor + # Set string value... 'toneScript.wordNumber' Word 'toneScript.currentWord$' + # endif + #endif + + # "broken" third tones + if index_regex(toneScript.inputWord$, "3") > 0 + toneScript.currentWord$ = replace$(toneScript.inputWord$, "3", "9", 0) + # Write name in list + toneScript.wordNumber = toneScript.wordNumber+1 if toneScript.createToneList = 1 select Table ToneList toneScript.listLength = Get number of rows toneScript.listLength = toneScript.listLength + 1 - for toneScript.currLength from toneScript.listLength to toneScript.wordNumber - Append row - Set string value... 'toneScript.currLength' Word ------EMPTY - endfor Set string value... 'toneScript.wordNumber' Word 'toneScript.currentWord$' endif - - # Actually, generate something + # Actually, generate something + call generateWord 'toneScript.generate$' 'toneScript.currentWord$' 'toneScript.upperRegister' + endif + + # 6 tones + if toneScript.syllableCount > 1 + toneScript.currentWord$ = replace_regex$(toneScript.inputWord$, "[\d+]", "6", 0) + # Write name in list + toneScript.wordNumber = toneScript.wordNumber+1 + if toneScript.createToneList = 1 + select Table ToneList + toneScript.listLength = Get number of rows + toneScript.listLength = toneScript.listLength + 1 + Set string value... 'toneScript.wordNumber' Word 'toneScript.currentWord$' + endif + # Actually, generate something + call generateWord 'toneScript.generate$' 'toneScript.currentWord$' 'toneScript.upperRegister' endif - - call generateWord 'toneScript.generate$' 'toneScript.currentWord$' 'toneScript.upperRegister' else call generateWord 'toneScript.generate$' 'toneScript.inputWord$' 'toneScript.upperRegister' endif diff --git a/sgc2.praat b/sgc2.praat index b5571e6..b3ac757 100644 --- a/sgc2.praat +++ b/sgc2.praat @@ -764,15 +764,17 @@ procedure record_sound .recordingTime demoShow() # In Windows XP interaction between demoWaitForInput and Record Sound blocks drawing the feedback - #if windows and endsWith(build_SHA$, " XP") - # # Display a pause window to flush the graphics buffer - # beginPause ("DESTROY WINDOW ") - # comment (" ") - # endPause ("DESTROY WINDOW ", 1) - # #call init_window - # demo Paint circle... Red 5 95 2 - # demoShow() - #endif + # This code might be removed # + if windows and endsWith(build_SHA$, " XP") + # Display a pause window to flush the graphics buffer + beginPause ("DESTROY WINDOW ") + comment (" ") + endPause ("DESTROY WINDOW ", 1) + #call init_window + demo Paint circle... Red 5 95 2 + demoShow() + endif + ############################## # Use a different recorder program if sgc.useAlternativeRecorder and fileReadable(sgc.recordCommandFile$) @@ -877,19 +879,22 @@ procedure sound_detection .sound$ .margin endif # The code below will suppress noise, but also weak third tones - # Remove buzzing and other obnoxious sounds (if switched on) - #for .i from 1 to .numberofIntervals - # select TextGrid Input'.sound$' - # .value$ = Get label of interval... 1 '.i' - # .begintime = Get starting point... 1 '.i' - # .endtime = Get end point... 1 '.i' + # This handles the problem that third tones can be realized with + # alternative cues, e.g, non-standard voice and very low levels # - # # Remove noise - # if .value$ = "silent" - # select Sound '.sound$' - # Set part to zero... '.begintime' '.endtime' at nearest zero crossing - # endif - #endfor + # Remove buzzing and other obnoxious sounds (if switched on) + for .i from 1 to .numberofIntervals + select TextGrid Input'.sound$' + .value$ = Get label of interval... 1 '.i' + .begintime = Get starting point... 1 '.i' + .endtime = Get end point... 1 '.i' + + # Remove noise + if .value$ = "silent" + select Sound '.sound$' + Set part to zero... '.begintime' '.endtime' at nearest zero crossing + endif + endfor # Select target sound .maximumIntensity = -1 -- 2.11.4.GIT