Test of creaky voice detector
[sgc2.git] / ToneProt / ToneRules.praat
blobc9c904c2bafb59e63525d5700f3ab25e405544ad
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
5 # (which they are).
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
21 # DO NOT ALTER THEM
22
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
31
33 # Procedure to scale the duration of the current syllable
34 procedure toneDuration
35         if toneScript.toneSyllable = 0
36                 .zeroToneFactor = 0.5
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
43         endif
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
51         endif
52     
53         # Next tone 0, then lengthen first syllable
54         if toneScript.nextTone = 0
55                 toneScript.toneFactor = toneScript.toneFactor * 1.2
56         endif
57 endproc
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
70 procedure toneRules
71     #
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))
80     # First tone
81         if toneScript.toneSyllable = 1
82         # Just a straight line
83         toneRules.startPoint = toneRules.levelFive
84         toneScript.endPoint = toneRules.levelFive
85         
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
90         endif
91         
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'
96     # Second tone
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
106             endif
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
112             # Go 1 semitone up
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
118         endif
119         # Define a midtoneScript.point at 1/3 of the duration
120         toneRules.midPoint = toneRules.startPoint
121              
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'
127         # Remaining duration
128         toneScript.point = toneScript.point + (toneScript.voicedDuration)*2/3
129         Add point... 'toneScript.point' 'toneScript.endPoint'
130     # Third tone
131         elsif toneScript.toneSyllable = 3
132         # Halfway the range
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
138         endif
139         # First syllable
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
157         else
158             toneScript.endPoint = toneRules.startPoint
159         endif
160     
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'
172     # Third tone with voice break
173         elsif toneScript.toneSyllable = 9
174         # Halfway the range
175         toneRules.startPoint = toneRules.levelThree
176         toneRules.lowestPoint = toneRules.levelOne * toneScript.threeSemit
177         # Protect pitch against "underflow"
178         if toneRules.lowestPoint < toneScript.absoluteMinimum
179             toneRules.lowestPoint = toneScript.absoluteMinimum
180         endif
181         # First syllable
182         if toneScript.nextTone < 0
183             toneScript.endPoint = toneRules.startPoint
184         # Anticipate rise in next tone
185         elsif toneScript.nextTone = 1 or toneScript.nextTone = 4
186             toneRules.lowestPoint = toneRules.levelOne / toneScript.twoSemit
187             toneScript.endPoint = toneRules.startPoint
188         # Anticipate rise in next tone and stay low
189         elsif toneScript.nextTone = 2
190             toneRules.lowestPoint = toneRules.levelOne / toneScript.twoSemit
191             toneScript.endPoint = toneRules.lowestPoint
192         # Last one was low, don't go so much lower
193         elsif toneScript.prevTone = 4
194             toneRules.lowestPoint = toneRules.levelOne * toneScript.oneSemit
195         # Anticipate rise in next tone and stay low
196         elsif toneScript.nextTone = 0
197             toneRules.lowestPoint = toneRules.levelOne
198             toneScript.endPoint = toneRules.lowestPoint / toneScript.sixSemit
199         else
200             toneScript.endPoint = toneRules.startPoint
201         endif
202     
203         # Write toneScript.points
204         Add point... 'toneScript.point' 'toneRules.startPoint'
205         # Go 1/3 of the duration down
206             toneScript.point = toneScript.point + (toneScript.voicedDuration)*2/6
207         Add point... 'toneScript.point' 'toneRules.lowestPoint'
208         
209         # voiceless break
210         .delta = 'toneScript.point' + 0.001
211         Add point... '.delta' 0
212         
213         # Go half the duration low
214             toneScript.point = toneScript.point + (toneScript.voicedDuration)*3/6
215             
216         # voiceless break
217         .delta = 'toneScript.point' - 0.001
218         Add point... '.delta' 0
219             
220         Add point... 'toneScript.point' 'toneRules.lowestPoint'
221         # Return in 1/6th of the duration
222             toneScript.point = toneScript.point + (toneScript.voicedDuration)*1/6
223         # Go on
224         Add point... 'toneScript.point' 'toneScript.endPoint'
225     # Fourth tone
226         elsif toneScript.toneSyllable = 4
227         # Start higher than tone 1 (by 2 semitones)
228         toneRules.startPoint = toneRules.levelFive / toneScript.twoSemit
229         # Go down the full range
230         toneScript.endPoint = toneRules.startPoint * toneScript.frequency_Range
231         
232         
233         # SPECIAL: Fall in following neutral tone
234             if toneScript.nextTone = 0
235                 toneScript.endPoint = toneScript.endPoint / toneScript.threeSemit
236         endif
237      
238         # Write toneScript.points
239         Add point... 'toneScript.point' 'toneRules.startPoint'
240         # A plateau for 1/3th
241         toneScript.point = toneScript.point + toneScript.voicedDuration*1/3
242         Add point... 'toneScript.point' 'toneRules.startPoint'
243         # Go down the rest
244         toneScript.point = toneScript.point + toneScript.voicedDuration*2/3
245         Add point... 'toneScript.point' 'toneScript.endPoint'
246     # Neutral tone
247         elsif toneScript.toneSyllable = 0
248         if toneScript.lastFrequency > 0
249             toneRules.startPoint = toneScript.lastFrequency
250         else
251             toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
252         endif
254         if toneScript.prevTone = 1
255             toneRules.startPoint = toneScript.lastFrequency * toneScript.twoSemit 
256         elsif toneScript.prevTone = 2
257             toneRules.startPoint = toneScript.lastFrequency
258         elsif toneScript.prevTone = 3
259             toneRules.startPoint = toneScript.lastFrequency / toneScript.oneSemit
260         elsif toneScript.prevTone = 4
261             toneRules.startPoint = toneScript.lastFrequency * toneScript.oneSemit
262         elsif toneScript.lastFrequency > 0
263             toneRules.startPoint = toneScript.lastFrequency * toneScript.oneSemit
264         endif
266         # Catch all errors\r
267         if toneRules.startPoint <= 0
268             toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
269         endif
270             
271        # Add spreading and some small or large de/inclination
272         if toneScript.prevTone = 1
273                 toneRules.midPoint = toneRules.startPoint * toneScript.frequency_Range / toneScript.oneSemit
274             toneScript.endPoint = toneRules.midPoint * toneScript.oneSemit
275         elsif toneScript.prevTone = 2
276             # 
277                 toneRules.midPoint = toneRules.startPoint * toneScript.fiveSemit
278             toneScript.endPoint = toneRules.midPoint * toneScript.twoSemit
279         elsif toneScript.prevTone = 3
280                 toneRules.midPoint = toneRules.startPoint / toneScript.twoSemit
281             toneScript.endPoint = toneRules.midPoint
282         elsif toneScript.prevTone = 4
283                 toneRules.midPoint = toneRules.startPoint * toneScript.threeSemit
284             toneScript.endPoint = toneRules.midPoint / toneScript.oneSemit
285         else
286                 toneRules.midPoint = toneRules.startPoint * toneScript.oneSemit
287             toneScript.endPoint = toneRules.midPoint
288         endif
289                 
290         # Add a very short break to force (disabled, maybe should be removed)
291                 if 0
292                 if toneScript.point = undefined
293                                 toneScript.point = 0
294                 endif
295                 
296                 Add point... 'toneScript.point' 0
297                         toneScript.point = toneScript.point + 1/toneRules.startPoint
298                 Add point... 'toneScript.point' 0
299                         toneScript.point = toneScript.point + toneScript.delta
300                 endif
301         
302         # Write toneScript.points first 2/3 then decaying 1/3
303         Add point... 'toneScript.point' 'toneRules.startPoint'
304                 toneScript.point = toneScript.point + (toneScript.voicedDuration - 1/toneRules.startPoint)*2/3
305             Add point... 'toneScript.point' 'toneRules.midPoint'
306                 toneScript.point = toneScript.point + (toneScript.voicedDuration - 1/toneRules.startPoint)*1/3
307             Add point... 'toneScript.point' 'toneScript.endPoint'
308     # Dutch intonation
309         else
310         # Start halfway of the range
311         toneRules.startPoint = toneRules.levelThree
312         # Or continue from last Dutch "tone"
313         if toneScript.prevTone = 6
314             toneRules.startPoint = toneScript.lastFrequency
315         endif
316         # Add declination
317         toneScript.endPoint = toneRules.startPoint * toneScript.oneSemit
318         
319         # Write toneScript.points
320         Add point... 'toneScript.point' 'toneRules.startPoint'
321         toneScript.point = toneScript.point + toneScript.voicedDuration
322         Add point... 'toneScript.point' 'toneScript.endPoint'
323         endif
324 endproc