New attempt to creacky voice detection in third tones
[sgc2.git] / ToneProt / ToneRules.praat
blob6e758ee52f87158f6ed5e9eb18689b702e299ef9
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, 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
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 or toneScript.prevTone = 9
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 or toneScript.toneSyllable = 9
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 or toneScript.prevTone = 9
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 or toneScript.toneSyllable = 9
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         
167             
168                 # Third tone with voice break
169             if toneScript.toneSyllable = 9
170                         # voiceless break
171                         .delta = 'toneScript.point' + 0.001
172                         Add point... '.delta' 0
173                 endif
174                 
175             # Go half the duration low
176                 toneScript.point = toneScript.point + (toneScript.voicedDuration)*3/6
177                 
178                 # Third tone with voice break
179             if toneScript.toneSyllable = 9
180                         # voiceless break
181                         # voiceless break
182                         .delta = 'toneScript.point' - 0.001
183                         Add point... '.delta' 0
184                 endif
185                 
186                 # Add final point of low (voiced)
187             Add point... 'toneScript.point' 'toneRules.lowestPoint'
188         
189         # Return in 1/6th of the duration
190             toneScript.point = toneScript.point + (toneScript.voicedDuration)*1/6
191         # Go on
192         Add point... 'toneScript.point' 'toneScript.endPoint'
194     # Fourth tone
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
200         
201         
202         # SPECIAL: Fall in following neutral tone
203             if toneScript.nextTone = 0
204                 toneScript.endPoint = toneScript.endPoint / toneScript.threeSemit
205         endif
206      
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'
212         # Go down the rest
213         toneScript.point = toneScript.point + toneScript.voicedDuration*2/3
214         Add point... 'toneScript.point' 'toneScript.endPoint'
215     # Neutral tone
216         elsif toneScript.toneSyllable = 0
217         if toneScript.lastFrequency > 0
218             toneRules.startPoint = toneScript.lastFrequency
219         else
220             toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
221         endif
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
233         endif
235         # Catch all errors\r
236         if toneRules.startPoint <= 0
237             toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
238         endif
239             
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
245             # 
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
254         else
255                 toneRules.midPoint = toneRules.startPoint * toneScript.oneSemit
256             toneScript.endPoint = toneRules.midPoint
257         endif
258                 
259         # Add a very short break to force (disabled, maybe should be removed)
260                 if 0
261                 if toneScript.point = undefined
262                                 toneScript.point = 0
263                 endif
264                 
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
269                 endif
270         
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'
277     # Dutch intonation
278         else
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
284         endif
285         # Add declination
286         toneScript.endPoint = toneRules.startPoint * toneScript.oneSemit
287         
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'
292         endif
293 endproc