Merge with git+ssh://sgc@fondialog1.hum.uva.nl/fro/git/sgc.git
[sgc.git] / SGC_ToneProt / ToneRules.praat
blobf276ca2a1be7cb1942244daa7356d5736a319f4d
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 # 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 # toneFactor:  Duration scale factor for current tone
14 # startPoint:  Start of the tone
15 # endPoint:    end of the tone
16 # lowestPoint: bottom of tone 3
17 # point: The time of the next pitch value in the contour
18 #        ONLY USE AS: point = point + <fraction> * voicedDuration
20 # The following values are given by the calling routine
21 # DO NOT ALTER THEM
22
23 # toneSyllable: tone number on the current syllable
24 # nextTone: tone number of next syllable or -1
25 # prevTone: tone number of previous syllable or -1
26 # lastFrequency: end-frequency of the previous syllable
28 # topLine: the frequency of the first tone
29 # frequency_Range: Range of tone four (1 octave)
30 # voicedDuration: Duration of voiced part of syllable
31
33 # Procedure to scale the duration of the current syllable
34 procedure toneDuration
35         if toneSyllable = 0
36                 zeroToneFactor = 0.5
37         if prevTone = 2
38             zeroToneFactor = 0.8 * zeroToneFactor
39         elsif prevTone = 3
40             zeroToneFactor = 1.1 * zeroToneFactor
41         elsif prevTone = 4
42             zeroToneFactor = 0.8 * zeroToneFactor
43         endif
44         toneFactor = zeroToneFactor * toneFactor
45         elsif toneSyllable = 2
46                 toneFactor = 0.8
47         elsif toneSyllable = 3
48                 toneFactor = 1.1
49     elsif toneSyllable = 4
50                 toneFactor = 0.8
51         endif
52     
53         # Next tone 0, then lengthen first syllable
54         if nextTone = 0
55                 toneFactor = toneFactor * 1.2
56         endif
57 endproc
59 # DO NOT CHANGE 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 '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     # First tone
72         if toneSyllable = 1
73         # Just a straight line
74         startPoint = topLine
75         endPoint = topLine
76         
77         # Two first tones, make them a little different
78         if prevTone = 1
79             startPoint = startPoint * 0.999
80             endPoint = endPoint * 0.999
81         endif
82         
83         # Write points
84         Add point... 'point' 'startPoint'
85         point = point + voicedDuration
86         Add point... 'point' 'endPoint'
87     # Second tone
88         elsif toneSyllable = 2
89         # Start halfway of the range - 1 semitone
90         startPoint = topLine * sqrt(frequency_Range) * oneSemit
91         # End 1 semitones above the first tone
92         endPoint = topLine / oneSemit
93         # Special case: 2 followed by 1, stop short of the top-line
94         # ie, 5 semitones above the start
95         if nextTone = 1
96             endPoint = startPoint / fiveSemit
97             endif
98             # Go lower if previous tone is 1
99             if prevTone = 1
100                 startPoint = startPoint * oneSemit
101         elsif prevTone = 4 or prevTone = 3
102             # Special case: 2 following 4 or 3
103             # Go 1 semitone up
104                 startPoint = lastFrequency / oneSemit
105             endPoint = topLine
106             elsif prevTone = 2
107         # Two consecutive tone 2, start 1 semitone higher
108                     startPoint = startPoint / oneSemit
109         endif
110         # Define a midpoint at 1/3 of the duration
111         midPoint = startPoint
112              
113         # Write points
114         Add point... 'point' 'startPoint'
115         # Next point a 1/3th of duration
116         point = point + (voicedDuration)/3
117         Add point... 'point' 'midPoint'
118         # Remaining duration
119         point = point + (voicedDuration)*2/3
120         Add point... 'point' 'endPoint'
121     # Third tone
122         elsif toneSyllable = 3
123         # Halfway the range
124         startPoint = topLine * sqrt(frequency_Range)
125         lowestPoint = topLine * frequency_Range * threeSemit
126         # Protect pitch against "underflow"
127         if lowestPoint < absoluteMinimum
128             lowestPoint = absoluteMinimum
129         endif
130         # First syllable
131         if nextTone < 0
132             endPoint = startPoint
133         # Anticipate rise in next tone
134         elsif nextTone = 1 or nextTone = 4
135             lowestPoint = topLine * frequency_Range / twoSemit
136             endPoint = startPoint
137         # Anticipate rise in next tone and stay low
138         elsif nextTone = 2
139             lowestPoint = topLine * frequency_Range / twoSemit
140             endPoint = lowestPoint
141         # Last one was low, don't go so much lower
142         elsif prevTone = 4
143             lowestPoint = topLine * frequency_Range * oneSemit
144         # Anticipate rise in next tone and stay low
145         elsif nextTone = 0
146             lowestPoint = topLine * frequency_Range
147             endPoint = lowestPoint / sixSemit
148         else
149             endPoint = startPoint
150         endif
151     
152         # Write points
153         Add point... 'point' 'startPoint'
154         # Go 1/3 of the duration down
155             point = point + (voicedDuration)*2/6
156         Add point... 'point' 'lowestPoint'
157         # Go half the duration low
158             point = point + (voicedDuration)*3/6
159         Add point... 'point' 'lowestPoint'
160         # Return in 1/6th of the duration
161             point = point + (voicedDuration)*1/6
162         Add point... 'point' 'endPoint'
163     # Fourth tone
164         elsif toneSyllable = 4
165         # Start higher than tone 1 (by 2 semitones)
166         startPoint = topLine / twoSemit
167         # Go down the full range
168         endPoint = startPoint * frequency_Range
169         
170         
171         # SPECIAL: Fall in following neutral tone
172             if nextTone = 0
173                 endPoint = endPoint / threeSemit
174         endif
175      
176         # Write points
177         Add point... 'point' 'startPoint'
178         # A plateau for 1/3th
179         point = point + voicedDuration*1/3
180         Add point... 'point' 'startPoint'
181         # Go down the rest
182         point = point + voicedDuration*2/3
183         Add point... 'point' 'endPoint'
184     # Neutral tone
185         elsif toneSyllable = 0
186         if lastFrequency > 0
187             startPoint = lastFrequency
188         else
189             startPoint = topLine * sqrt(frequency_Range) / oneSemit
190         endif
192         if prevTone = 1
193             startPoint = lastFrequency * twoSemit 
194         elsif prevTone = 2
195             startPoint = lastFrequency
196         elsif prevTone = 3
197             startPoint = lastFrequency / oneSemit
198         elsif prevTone = 4
199             startPoint = lastFrequency * oneSemit
200         elsif lastFrequency > 0
201             startPoint = lastFrequency * oneSemit
202         endif
203         # Add spreading and some small or large de/inclination
204         if prevTone = 1
205                 midPoint = startPoint * frequency_Range / oneSemit
206             endPoint = midPoint * oneSemit
207         elsif prevTone = 2
208             # 
209                 midPoint = startPoint * fiveSemit
210             endPoint = midPoint * twoSemit
211         elsif prevTone = 3
212                 midPoint = startPoint / twoSemit
213             endPoint = midPoint
214         elsif prevTone = 4
215                 midPoint = startPoint * threeSemit
216             endPoint = midPoint / oneSemit
217         else
218                 midPoint = startPoint * oneSemit
219             endPoint = midPoint * oneSemit
220         endif
221                 
222         if startPoint <= 0
223             startPoint = topLine * sqrt(frequency_Range) * oneSemit
224         endif
225             
226         # Add a very short break to force
227         if point = undefined
228             point = 0
229         endif
230         
231         Add point... 'point' 0
232                 point = point + 1/startPoint
233         Add point... 'point' 0
234                 point = point + delta
235         
236         # Write points first 2/3 then decaying 1/3
237         Add point... 'point' 'startPoint'
238                 point = point + (voicedDuration - 1/startPoint)*2/3
239             Add point... 'point' 'midPoint'
240                 point = point + (voicedDuration - 1/startPoint)*1/3
241             Add point... 'point' 'endPoint'
242     # Dutch intonation
243         else
244         # Start halfway of the range
245         startPoint = topLine * sqrt(frequency_Range)
246         # Or continue from last Dutch "tone"
247         if prevTone = 6
248             startPoint = lastFrequency
249         endif
250         # Add declination
251         endPoint = startPoint * oneSemit
252         
253         # Write points
254         Add point... 'point' 'startPoint'
255         point = point + voicedDuration
256         Add point... 'point' 'endPoint'
257         endif
258 endproc