From 224792d948d437708b265546c0ba4ced3cde2e68 Mon Sep 17 00:00:00 2001 From: Rob van Son Date: Wed, 7 Dec 2016 14:23:40 +0100 Subject: [PATCH] Added segmentation for third tones as part of creaky voice detection, working version --- ToneProt/SGC_ToneProt.praat | 65 +++++++++++++++++---------------------------- ToneProt/ToneScript.praat | 52 +++++++++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 48 deletions(-) diff --git a/ToneProt/SGC_ToneProt.praat b/ToneProt/SGC_ToneProt.praat index 8fc686a..3505fdc 100644 --- a/ToneProt/SGC_ToneProt.praat +++ b/ToneProt/SGC_ToneProt.praat @@ -159,51 +159,34 @@ procedure sgc_ToneProt sgc_ToneProt.currentSound$ sgc_ToneProt.pinyin$ sgc_ToneP select Pitch 'sgc_ToneProt.pinyin$' .generatedWord3 = selected("Pitch") - # Lower cutoff is 1/2 semitone above the 0.05 quantile - .lowerCutOff = Get quantile: 0, 0, 0.05, "Hertz" - .lowerCutOff /= sqrt(toneScript.oneSemit) # Create a tier with low part of the third tone as intervals - select .generatedWord3 - .modelDuration = Get total duration - .numFrames = Get number of frames - .prevV = Get value in frame: 1, "Hertz" - if .prevV = undefined or .prevV <= 0 - .prevV = sgc_ToneProt.register - endif - .prevT = 0 - .numIntervals = 1 - .pitchTier = Create TextGrid: 0, .modelDuration, "pitch", "" - select .pitchTier - if .prevV > .lowerCutOff - Set interval text: 1, .numIntervals, "NotLow" - elsif .prevV <= .lowerCutOff - Set interval text: 1, .numIntervals, "3Low" - endif - .lowPresent = 0 - for .s to .numFrames - select .generatedWord3 - .frameT = Get time from frame number: .s - .value = Get value in frame: .s, "Hertz" - if .value = undefined or .value <= 0 - .value = sgc_ToneProt.register - endif - if .value > .lowerCutOff and .prevV <= .lowerCutOff - select .pitchTier - Insert boundary: 1, (.frameT+.prevT)/2 - .numIntervals += 1 - Set interval text: 1, .numIntervals, "NotLow" - elsif .value <= .lowerCutOff and .prevV > .lowerCutOff - select .pitchTier - Insert boundary: 1, (.frameT+.prevT)/2 - .numIntervals += 1 - Set interval text: 1, .numIntervals, "3Low" + call generateWord TextGrid 'sgc_ToneProt.pinyin$' 'sgc_ToneProt.register' + .lowPresent = 0 + select TextGrid 'sgc_ToneProt.pinyin$' + .pitchTier = selected("TextGrid") + .numIntervals = Get number of intervals: 1 + for .int to .numIntervals + select .pitchTier + .label$ = Get label of interval: 1, .int + if .label$ = "3" or .label$ = "9" .lowPresent += 1 + Set interval text: 1, .int, "3onset" + .start = Get starting point: 1, .int + .end = Get end point: 1, .int + .newStart = .start + (.end - .start)/3 + .newEnd = .start + 5*(.end - .start)/6 + # Add interval to TextGrid + select .pitchTier + Insert boundary: 1, .newStart + Insert boundary: 1, .newEnd + Set interval text: 1, .int+1, "3Low" + Set interval text: 1, .int+2, "3offset" + # Dangerous stuff! + .int += 2 endif - .prevV = .value - .prevT = .frameT endfor - + # DTW of .generatedWord9 with sourcePitch if .lowPresent > 0 select te.recordedPitch @@ -246,7 +229,7 @@ procedure sgc_ToneProt sgc_ToneProt.currentSound$ sgc_ToneProt.pinyin$ sgc_ToneP # Weigh creacky voice by number of syllables toneProt.creackyThree /= toneScript.syllableCount endif - + # Clean up select .jitterShimmer plus .pitchTier diff --git a/ToneProt/ToneScript.praat b/ToneProt/ToneScript.praat index ceb75b8..d2a5b6d 100644 --- a/ToneProt/ToneScript.praat +++ b/ToneProt/ToneScript.praat @@ -242,11 +242,13 @@ procedure addToneMovement .syllable$ toneScript.topLine toneScript.prevTone tone toneScript.toneFactor = toneScript.toneFactor * toneScript.durationScale # Unvoiced part + toneScript.unvoicedDuration = 0 if rindex_regex(toneScript.voicingSyllable$, "U") = 1 toneScript.point = toneScript.point + toneScript.delta Add point... 'toneScript.point' 0 toneScript.point = toneScript.point + toneScript.segmentDuration * toneScript.toneFactor Add point... 'toneScript.point' 0 + toneScript.unvoicedDuration = toneScript.segmentDuration * toneScript.toneFactor endif # Voiced part toneScript.voiceLength$ = replace_regex$(toneScript.voicingSyllable$, "U*([CV]+)U*", "\1", 0) @@ -279,7 +281,14 @@ procedure wordToTones .wordInput$ toneScript.highPitch syllable'toneScript.syllableCount'$ = replace_regex$(.currentRest$, "^([^\d]+[\d]+)(.*)$", "\1", 1) toneScript.currentSyllable$ = syllable'toneScript.syllableCount'$ - # Get the tone + # For next round + .currentRest$ = replace_regex$(.currentRest$, "^([^\d]+[\d]+)(.*)$", "\2", 1) + # Get next syllable + .nextSyllable$ = replace_regex$(.currentRest$, "^([^\d]+[\d]+)(.*)$", "\1", 1) + call extractTone '.nextSyllable$' + toneScript.nextTone = toneScript.toneSyllable + + # Get the current tone call extractTone 'toneScript.currentSyllable$' toneScript.toneSyllable'toneScript.syllableCount' = toneScript.toneSyllable toneScript.currentTone = toneScript.toneSyllable'toneScript.syllableCount' @@ -298,29 +307,38 @@ procedure wordToTones .wordInput$ toneScript.highPitch .length = .length + toneScript.toneFactor * (length(voicingSyllable'toneScript.syllableCount'$) * (toneScript.segmentDuration + toneScript.delta) + toneScript.fixedDuration) - # Next round - .currentRest$ = replace_regex$(.currentRest$, "^([^\d]+[\d]+)(.*)$", "\2", 1) - # Safety valve if toneScript.syllableCount > 2000 exit endif endwhile - + # Create tone pattern toneScript.pitchTier = Create PitchTier... '.wordInput$' 0 '.length' toneScript.pitchTierWord$ = .wordInput$ + # Create TextGrid with syllables + toneScript.textGrid = Create TextGrid: 0, .length, "Tones", "" + Rename: .wordInput$ + .int = 0; # Add start toneScript.margin + select toneScript.pitchTier toneScript.lastFrequency = 0 toneScript.point = 0 Add point... 'toneScript.point' 0 toneScript.point = toneScript.margin Add point... 'toneScript.point' 0 + + # Add interval to TextGrid + select toneScript.textGrid + Insert boundary: 1, toneScript.point + .int += 1 + Set interval text: 1, .int, "" toneScript.lastTone = -1 toneScript.followTone = -1 for .i from 1 to toneScript.syllableCount + select toneScript.pitchTier toneScript.currentSyllable$ = syllable'.i'$ toneScript.currentTone = toneScript.toneSyllable'.i' toneScript.followTone = -1 @@ -328,13 +346,25 @@ procedure wordToTones .wordInput$ toneScript.highPitch .j = .i+1 toneScript.followTone = toneScript.toneSyllable'.j' endif - + .lastPoint = toneScript.point call addToneMovement 'toneScript.currentSyllable$' 'toneScript.highPitch' 'toneScript.lastTone' 'toneScript.followTone' toneScript.lastTone = toneScript.currentTone + + # Add interval to TextGrid + select toneScript.textGrid + if toneScript.unvoicedDuration > 0 + Insert boundary: 1, .lastPoint + toneScript.unvoicedDuration + .int += 1 + Set interval text: 1, .int, "U" + endif + Insert boundary: 1, toneScript.point + .int += 1 + Set interval text: 1, .int, "'toneScript.currentTone'" endfor # Add end toneScript.margin + select toneScript.pitchTier toneScript.point = toneScript.point + toneScript.delta Add point... 'toneScript.point' 0 toneScript.point = toneScript.point + toneScript.margin @@ -345,6 +375,14 @@ procedure generateWord toneScript.whatToGenerate$ toneScript.theWord$ toneScript # First generate model contour call wordToTones 'toneScript.theWord$' 'toneScript.upperRegister' + + if index(toneScript.whatToGenerate$, "TextGrid") <= 0 + if variableExists("toneScript.textGrid") and toneScript.textGrid > 0 + select toneScript.textGrid + Remove + endif + endif + # Generate pitch if toneScript.pitchTierWord$ = toneScript.theWord$ select toneScript.pitchTier @@ -410,7 +448,7 @@ procedure generateWord toneScript.whatToGenerate$ toneScript.theWord$ toneScript # Clean up select PitchTier 'toneScript.theWord$' - if rindex_regex(toneScript.whatToGenerate$, "Sound") > 0 + if rindex_regex(toneScript.whatToGenerate$, "(Sound|TextGrid)") > 0 plus Pitch 'toneScript.theWord$' endif Remove -- 2.11.4.GIT