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
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
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
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
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
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'
166 # Go half the duration low
167 toneScript.point = toneScript.point + (toneScript.voicedDuration)*3/6
168 Add point... 'toneScript.point' 'toneRules.lowestPoint'
169 # Return in 1/6th of the duration
170 toneScript.point = toneScript.point + (toneScript.voicedDuration)*1/6
171 Add point... 'toneScript.point' 'toneScript.endPoint'
173 elsif toneScript.toneSyllable = 4
174 # Start higher than tone 1 (by 2 semitones)
175 toneRules.startPoint = toneRules.levelFive / toneScript.twoSemit
176 # Go down the full range
177 toneScript.endPoint = toneRules.startPoint * toneScript.frequency_Range
180 # SPECIAL: Fall in following neutral tone
181 if toneScript.nextTone = 0
182 toneScript.endPoint = toneScript.endPoint / toneScript.threeSemit
185 # Write toneScript.points
186 Add point... 'toneScript.point' 'toneRules.startPoint'
187 # A plateau for 1/3th
188 toneScript.point = toneScript.point + toneScript.voicedDuration*1/3
189 Add point... 'toneScript.point' 'toneRules.startPoint'
191 toneScript.point = toneScript.point + toneScript.voicedDuration*2/3
192 Add point... 'toneScript.point' 'toneScript.endPoint'
194 elsif toneScript.toneSyllable = 0
195 if toneScript.lastFrequency > 0
196 toneRules.startPoint = toneScript.lastFrequency
198 toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
201 if toneScript.prevTone = 1
202 toneRules.startPoint = toneScript.lastFrequency * toneScript.twoSemit
203 elsif toneScript.prevTone = 2
204 toneRules.startPoint = toneScript.lastFrequency
205 elsif toneScript.prevTone = 3
206 toneRules.startPoint = toneScript.lastFrequency / toneScript.oneSemit
207 elsif toneScript.prevTone = 4
208 toneRules.startPoint = toneScript.lastFrequency * toneScript.oneSemit
209 elsif toneScript.lastFrequency > 0
210 toneRules.startPoint = toneScript.lastFrequency * toneScript.oneSemit
214 if toneRules.startPoint <= 0
215 toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
218 # Add spreading and some small or large de/inclination
219 if toneScript.prevTone = 1
220 toneRules.midPoint = toneRules.startPoint * toneScript.frequency_Range / toneScript.oneSemit
221 toneScript.endPoint = toneRules.midPoint * toneScript.oneSemit
222 elsif toneScript.prevTone = 2
224 toneRules.midPoint = toneRules.startPoint * toneScript.fiveSemit
225 toneScript.endPoint = toneRules.midPoint * toneScript.twoSemit
226 elsif toneScript.prevTone = 3
227 toneRules.midPoint = toneRules.startPoint / toneScript.twoSemit
228 toneScript.endPoint = toneRules.midPoint
229 elsif toneScript.prevTone = 4
230 toneRules.midPoint = toneRules.startPoint * toneScript.threeSemit
231 toneScript.endPoint = toneRules.midPoint / toneScript.oneSemit
233 toneRules.midPoint = toneRules.startPoint * toneScript.oneSemit
234 toneScript.endPoint = toneRules.midPoint
237 # Add a very short break to force (disabled, maybe should be removed)
239 if toneScript.point = undefined
243 Add point... 'toneScript.point' 0
244 toneScript.point = toneScript.point + 1/toneRules.startPoint
245 Add point... 'toneScript.point' 0
246 toneScript.point = toneScript.point + toneScript.delta
249 # Write toneScript.points first 2/3 then decaying 1/3
250 Add point... 'toneScript.point' 'toneRules.startPoint'
251 toneScript.point = toneScript.point + (toneScript.voicedDuration - 1/toneRules.startPoint)*2/3
252 Add point... 'toneScript.point' 'toneRules.midPoint'
253 toneScript.point = toneScript.point + (toneScript.voicedDuration - 1/toneRules.startPoint)*1/3
254 Add point... 'toneScript.point' 'toneScript.endPoint'
257 # Start halfway of the range
258 toneRules.startPoint = toneRules.levelThree
259 # Or continue from last Dutch "tone"
260 if toneScript.prevTone = 6
261 toneRules.startPoint = toneScript.lastFrequency
264 toneScript.endPoint = toneRules.startPoint * toneScript.oneSemit
266 # Write toneScript.points
267 Add point... 'toneScript.point' 'toneRules.startPoint'
268 toneScript.point = toneScript.point + toneScript.voicedDuration
269 Add point... 'toneScript.point' 'toneScript.endPoint'