Handle broken wordlists and audio files
[sgc2.git] / ToneProt / ToneRules.praat
blob986eb93cfdcdf860c7538361511799ffd2393c38
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     # Fourth tone
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
178         
179         
180         # SPECIAL: Fall in following neutral tone
181             if toneScript.nextTone = 0
182                 toneScript.endPoint = toneScript.endPoint / toneScript.threeSemit
183         endif
184      
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'
190         # Go down the rest
191         toneScript.point = toneScript.point + toneScript.voicedDuration*2/3
192         Add point... 'toneScript.point' 'toneScript.endPoint'
193     # Neutral tone
194         elsif toneScript.toneSyllable = 0
195         if toneScript.lastFrequency > 0
196             toneRules.startPoint = toneScript.lastFrequency
197         else
198             toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
199         endif
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
211         endif
213         # Catch all errors\r
214         if toneRules.startPoint <= 0
215             toneRules.startPoint = toneRules.levelThree / toneScript.oneSemit
216         endif
217             
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
223             # 
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
232         else
233                 toneRules.midPoint = toneRules.startPoint * toneScript.oneSemit
234             toneScript.endPoint = toneRules.midPoint
235         endif
236                 
237         # Add a very short break to force
238         if toneScript.point = undefined
239             toneScript.point = 0
240         endif
241         
242         Add point... 'toneScript.point' 0
243                 toneScript.point = toneScript.point + 1/toneRules.startPoint
244         Add point... 'toneScript.point' 0
245                 toneScript.point = toneScript.point + toneScript.delta
246         
247         # Write toneScript.points first 2/3 then decaying 1/3
248         Add point... 'toneScript.point' 'toneRules.startPoint'
249                 toneScript.point = toneScript.point + (toneScript.voicedDuration - 1/toneRules.startPoint)*2/3
250             Add point... 'toneScript.point' 'toneRules.midPoint'
251                 toneScript.point = toneScript.point + (toneScript.voicedDuration - 1/toneRules.startPoint)*1/3
252             Add point... 'toneScript.point' 'toneScript.endPoint'
253     # Dutch intonation
254         else
255         # Start halfway of the range
256         toneRules.startPoint = toneRules.levelThree
257         # Or continue from last Dutch "tone"
258         if toneScript.prevTone = 6
259             toneRules.startPoint = toneScript.lastFrequency
260         endif
261         # Add declination
262         toneScript.endPoint = toneRules.startPoint * toneScript.oneSemit
263         
264         # Write toneScript.points
265         Add point... 'toneScript.point' 'toneRules.startPoint'
266         toneScript.point = toneScript.point + toneScript.voicedDuration
267         Add point... 'toneScript.point' 'toneScript.endPoint'
268         endif
269 endproc