1 # The rules for constructing the tone contours.
3 # This procedure works because in Praat, there is no namespace
4 # separation. All variables behave as if they are global
7 # toneScript.toneSyllable is the tone number on the current syllable
8 # 1-4, 0=neutral, 6=Dutch (garbage) intonation, 9=3, but with an unvoiced low segment
10 # These procedures set the following pareameters
11 # and use them to create a Pitch Tier:
13 # toneScript.toneFactor: Duration scale factor for current tone
14 # toneRules.startPoint: Start of the tone
15 # toneScript.endPoint: end of the tone
16 # toneRules.lowestPoint: bottom of tone 3
17 # toneScript.point: The time of the next pitch value in the contour
18 # ONLY USE AS: toneScript.point = toneScript.point + <fraction> * toneScript.voicedDuration
20 # The following values are given by the calling routine
23 # toneScript.toneSyllable: tone number on the current syllable
24 # toneScript.nextTone: tone number of next syllable or -1
25 # toneScript.prevTone: tone number of previous syllable or -1
26 # toneScript.lastFrequency: end-frequency of the previous syllable
28 # toneScript.topLine: the frequency of the first tone
29 # toneScript.frequency_Range: Range of tone four (1 toneScript.octave)
30 # toneScript.voicedDuration: Duration of voiced part of syllable
33 # Procedure to scale the duration of the current syllable
34 procedure toneDuration
35 if toneScript.toneSyllable = 0
37 if toneScript.prevTone = 2
38 .zeroToneFactor = 0.8 * .zeroToneFactor
39 elsif toneScript.prevTone = 3 or toneScript.prevTone = 9
40 .zeroToneFactor = 1.1 * .zeroToneFactor
41 elsif toneScript.prevTone = 4
42 .zeroToneFactor = 0.8 * .zeroToneFactor
44 toneScript.toneFactor = .zeroToneFactor * toneScript.toneFactor
45 elsif toneScript.toneSyllable = 2
46 toneScript.toneFactor = 0.8
47 elsif toneScript.toneSyllable = 3 or toneScript.toneSyllable = 9
48 toneScript.toneFactor = 1.1
49 elsif toneScript.toneSyllable = 4
50 toneScript.toneFactor = 0.8
53 # Next tone 0, then lengthen first syllable
54 if toneScript.nextTone = 0
55 toneScript.toneFactor = toneScript.toneFactor * 1.2
59 # DO NOT CHANGE toneScript.toneFactor BELOW THIS POINT
61 # Rules to create a tone
63 # Do not mess with the 'Add point...' commands
64 # unless you know what you are doing
65 # The 'toneScript.point =' defines the time of the next pitch value
67 # start * ?Semit is a fall
68 # start / ?Semit is a rise
72 # Tone toneRules.levels 1-5
73 # Defined relative to the topline and the frequency range
74 toneRules.levelFive = toneScript.topLine
75 toneRules.levelOne = toneScript.topLine * toneScript.frequency_Range
76 toneRules.levelThree = toneScript.topLine * sqrt(toneScript.frequency_Range)
77 toneRules.levelTwo = toneScript.topLine * sqrt(sqrt(toneScript.frequency_Range))
78 toneRules.levelFour = toneRules.levelOne / sqrt(sqrt(toneScript.frequency_Range))
81 if toneScript.toneSyllable = 1
82 # Just a straight line
83 toneRules.startPoint = toneRules.levelFive
84 toneScript.endPoint = toneRules.levelFive
86 # Two first tones, make them a little different
87 if toneScript.prevTone = 1
88 toneRules.startPoint = toneRules.startPoint * 0.999
89 toneScript.endPoint = toneScript.endPoint * 0.999
92 # Write toneScript.points
93 Add point... 'toneScript.point' 'toneRules.startPoint'
94 toneScript.point = toneScript.point + toneScript.voicedDuration
95 Add point... 'toneScript.point' 'toneScript.endPoint'
97 elsif toneScript.toneSyllable = 2
98 # Start halfway of the range - 1 semitone
99 toneRules.startPoint = toneRules.levelThree * toneScript.oneSemit
100 # End 1 semitones above the first tone
101 toneScript.endPoint = toneRules.levelFive / toneScript.oneSemit
102 # Special case: 2 followed by 1, stop short of the top-line
103 # ie, 5 semitones above the start
104 if toneScript.nextTone = 1
105 toneScript.endPoint = toneRules.startPoint / toneScript.fiveSemit
107 # Go lower if previous tone is 1
108 if toneScript.prevTone = 1
109 toneRules.startPoint = toneRules.startPoint * toneScript.oneSemit
110 elsif toneScript.prevTone = 4 or toneScript.prevTone = 3 or toneScript.prevTone = 9
111 # Special case: 2 following 4 or 3
113 toneRules.startPoint = toneScript.lastFrequency / toneScript.oneSemit
114 toneScript.endPoint = toneRules.levelFive
115 elsif toneScript.prevTone = 2
116 # Two consecutive tone 2, start 1 semitone higher
117 toneRules.startPoint = toneRules.startPoint / toneScript.oneSemit
119 # Define a midtoneScript.point at 1/3 of the duration
120 toneRules.midPoint = toneRules.startPoint
122 # Write toneScript.points
123 Add point... 'toneScript.point' 'toneRules.startPoint'
124 # Next toneScript.point a 1/3th of duration
125 toneScript.point = toneScript.point + (toneScript.voicedDuration)/3
126 Add point... 'toneScript.point' 'toneRules.midPoint'
128 toneScript.point = toneScript.point + (toneScript.voicedDuration)*2/3
129 Add point... 'toneScript.point' 'toneScript.endPoint'
131 elsif toneScript.toneSyllable = 3 or toneScript.toneSyllable = 9
133 toneRules.startPoint = toneRules.levelThree
134 toneRules.lowestPoint = toneRules.levelOne * toneScript.threeSemit
135 # Protect pitch against "underflow"
136 if toneRules.lowestPoint < toneScript.absoluteMinimum
137 toneRules.lowestPoint = toneScript.absoluteMinimum
140 if toneScript.nextTone < 0
141 toneScript.endPoint = toneRules.startPoint
142 # Anticipate rise in next tone
143 elsif toneScript.nextTone = 1 or toneScript.nextTone = 4
144 toneRules.lowestPoint = toneRules.levelOne / toneScript.twoSemit
145 toneScript.endPoint = toneRules.startPoint
146 # Anticipate rise in next tone and stay low
147 elsif toneScript.nextTone = 2
148 toneRules.lowestPoint = toneRules.levelOne / toneScript.twoSemit
149 toneScript.endPoint = toneRules.lowestPoint
150 # Last one was low, don't go so much lower
151 elsif toneScript.prevTone = 4
152 toneRules.lowestPoint = toneRules.levelOne * toneScript.oneSemit
153 # Anticipate rise in next tone and stay low
154 elsif toneScript.nextTone = 0
155 toneRules.lowestPoint = toneRules.levelOne
156 toneScript.endPoint = toneRules.lowestPoint / toneScript.sixSemit
158 toneScript.endPoint = toneRules.startPoint
161 # Write toneScript.points
162 Add point... 'toneScript.point' 'toneRules.startPoint'
163 # Go 1/3 of the duration down
164 toneScript.point = toneScript.point + (toneScript.voicedDuration)*2/6
165 Add point... 'toneScript.point' 'toneRules.lowestPoint'
168 # Third tone with voice break
169 if toneScript.toneSyllable = 9
171 .delta = 'toneScript.point' + 0.001
172 Add point... '.delta' 0
175 # Go half the duration low
176 toneScript.point = toneScript.point + (toneScript.voicedDuration)*3/6
178 # Third tone with voice break
179 if toneScript.toneSyllable = 9
182 .delta = 'toneScript.point' - 0.001
183 Add point... '.delta' 0
186 # Add final point of low (voiced)
187 Add point... 'toneScript.point' 'toneRules.lowestPoint'
189 # Return in 1/6th of the duration
190 toneScript.point = toneScript.point + (toneScript.voicedDuration)*1/6
192 Add point... 'toneScript.point' 'toneScript.endPoint'
195 elsif toneScript.toneSyllable = 4
196 # Start higher than tone 1 (by 2 semitones)
197 toneRules.startPoint = toneRules.levelFive / toneScript.twoSemit
198 # Go down the full range
199 toneScript.endPoint = toneRules.startPoint * toneScript.frequency_Range
202 # SPECIAL: Fall in following neutral tone
203 if toneScript.nextTone = 0
204 toneScript.endPoint = toneScript.endPoint / toneScript.threeSemit
207 # Write toneScript.points
208 Add point... 'toneScript.point' 'toneRules.startPoint'
209 # A plateau for 1/3th
210 toneScript.point = toneScript.point + toneScript.voicedDuration*1/3
211 Add point... 'toneScript.point' 'toneRules.startPoint'
213 toneScript.point = toneScript.point + toneScript.voicedDuration*2/3
214 Add point... 'toneScript.point' 'toneScript.endPoint'
216 elsif toneScript.toneSyllable = 0
217 if toneScript.lastFrequency > 0
218 toneRules.startPoint = toneScript.lastFrequency
220 toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
223 if toneScript.prevTone = 1
224 toneRules.startPoint = toneScript.lastFrequency * toneScript.twoSemit
225 elsif toneScript.prevTone = 2
226 toneRules.startPoint = toneScript.lastFrequency
227 elsif toneScript.prevTone = 3 or toneScript.prevTone = 9
228 toneRules.startPoint = toneScript.lastFrequency / toneScript.oneSemit
229 elsif toneScript.prevTone = 4
230 toneRules.startPoint = toneScript.lastFrequency * toneScript.oneSemit
231 elsif toneScript.lastFrequency > 0
232 toneRules.startPoint = toneScript.lastFrequency * toneScript.oneSemit
236 if toneRules.startPoint <= 0
237 toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
240 # Add spreading and some small or large de/inclination
241 if toneScript.prevTone = 1
242 toneRules.midPoint = toneRules.startPoint * toneScript.frequency_Range / toneScript.oneSemit
243 toneScript.endPoint = toneRules.midPoint * toneScript.oneSemit
244 elsif toneScript.prevTone = 2
246 toneRules.midPoint = toneRules.startPoint * toneScript.fiveSemit
247 toneScript.endPoint = toneRules.midPoint * toneScript.twoSemit
248 elsif toneScript.prevTone = 3 or toneScript.prevTone = 9
249 toneRules.midPoint = toneRules.startPoint / toneScript.twoSemit
250 toneScript.endPoint = toneRules.midPoint
251 elsif toneScript.prevTone = 4
252 toneRules.midPoint = toneRules.startPoint * toneScript.threeSemit
253 toneScript.endPoint = toneRules.midPoint / toneScript.oneSemit
255 toneRules.midPoint = toneRules.startPoint * toneScript.oneSemit
256 toneScript.endPoint = toneRules.midPoint
259 # Add a very short break to force (disabled, maybe should be removed)
261 if toneScript.point = undefined
265 Add point... 'toneScript.point' 0
266 toneScript.point = toneScript.point + 1/toneRules.startPoint
267 Add point... 'toneScript.point' 0
268 toneScript.point = toneScript.point + toneScript.delta
271 # Write toneScript.points first 2/3 then decaying 1/3
272 Add point... 'toneScript.point' 'toneRules.startPoint'
273 toneScript.point = toneScript.point + (toneScript.voicedDuration - 1/toneRules.startPoint)*2/3
274 Add point... 'toneScript.point' 'toneRules.midPoint'
275 toneScript.point = toneScript.point + (toneScript.voicedDuration - 1/toneRules.startPoint)*1/3
276 Add point... 'toneScript.point' 'toneScript.endPoint'
279 # Start halfway of the range
280 toneRules.startPoint = toneRules.levelThree
281 # Or continue from last Dutch "tone"
282 if toneScript.prevTone = 6
283 toneRules.startPoint = toneScript.lastFrequency
286 toneScript.endPoint = toneRules.startPoint * toneScript.oneSemit
288 # Write toneScript.points
289 Add point... 'toneScript.point' 'toneRules.startPoint'
290 toneScript.point = toneScript.point + toneScript.voicedDuration
291 Add point... 'toneScript.point' 'toneScript.endPoint'