Corrections in handling missing neutral tones
[sgc2.git] / MainPage.praat
blob2ceb96e793600276578a70406716caa08542ccc3
2 # SpeakGoodChinese 2.0
3
4 # Praat script handling buttons page
6 #     SpeakGoodChinese: MainPage.praat loads the code needed for the 
7 #     main, practice, page of SGC2 and the sound handling and recognition.
8 #     
9 #     Copyright (C) 2007-2010  R.J.J.H. van Son and 2010 the Netherlands Cancer Institute
10 #     The SpeakGoodChinese team are:
11 #     Guangqin Chen, Zhonyan Chen, Stefan de Koning, Eveline van Hagen, 
12 #     Rob van Son, Dennis Vierkant, David Weenink
13
14 #     This program is free software; you can redistribute it and/or modify
15 #     it under the terms of the GNU General Public License as published by
16 #     the Free Software Foundation; either version 2 of the License, or
17 #     (at your option) any later version.
18
19 #     This program is distributed in the hope that it will be useful,
20 #     but WITHOUT ANY WARRANTY; without even the implied warranty of
21 #     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 #     GNU General Public License for more details.
23
24 #     You should have received a copy of the GNU General Public License
25 #     along with this program; if not, write to the Free Software
26 #     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
27
28 # Includes at the bottom
30 ###############################################################
32 # Button Drawing Routines
34 ###############################################################
36 procedure DrawPrevious .color$ .x .y .size
37         demo '.color$'
38         .size *= 2/3
39         call drawTriangle -1 .x .y .size
40         .currentX = drawTriangle.currentX
41         .endX = .currentX - 0.5
42         .lowY = .y - .size
43         .highY = .y + .size
44         demo Paint rectangle... '.color$' '.currentX' '.endX' '.lowY' '.highY'
45 endproc
47 procedure DrawNext .color$ .x .y .size
48         demo '.color$'
49         .size *= 2/3
50         call drawTriangle 1 .x .y .size
51         .currentX = drawTriangle.currentX
52         .endX = .currentX + 0.5
53         .lowY = .y - .size
54         .highY = .y + .size
55         demo Paint rectangle... '.color$' '.currentX' '.endX' '.lowY' '.highY'
56 endproc
58 procedure DrawWordListUp .color$ .x .y .size
59     .xleft = .x - .size
60     .xright = .x + .size
61     .xmidleft = .x + 0.1
62     .xmidright = .x - 0.1
63     .ylow = .y
64     .yhigh = .y + .size
65         demo '.color$'
66         demo Line width... 3
67         demo Draw line... .xleft .ylow .xmidleft .yhigh
68         demo Draw line... .xright .ylow .xmidright .yhigh
69         demo Line width... 'defaultLineWidth'
70         demo Black
71 endproc
73 procedure DrawWordListDown .color$ .x .y .size
74     .xleft = .x - .size
75     .xright = .x + .size
76     .xmidleft = .x + 0.1
77     .xmidright = .x - 0.1
78     .yhigh = .y + .size
79     .ylow = .y
80         demo '.color$'
81         demo Line width... 3
82         demo Draw line... .xleft .yhigh .xmidleft .ylow
83         demo Draw line... .xright .yhigh .xmidright .ylow
84         demo Line width... 'defaultLineWidth'
85         demo Black
86 endproc
88 procedure drawTriangle .direction .x .y .size
89         # Make sure direction = +/- 1
90         if .direction = 0
91                 .direction = 1 
92         endif
93         .direction /= abs(.direction)
94         
95         .offset = 0.01
96         .currentHeight = .size
97         .currentX = .x - .direction*.size
98         
99         demo Line width... 2.0
101         while .currentHeight> 0
102                 .ystart = .y + .currentHeight
103                 .yend = .y - .currentHeight
104                 demo Draw line... .currentX .ystart .currentX .yend
105                 .currentHeight -= .offset *3/4
106                 .currentX += .direction*.offset * 1.5
107         endwhile
108         demo Line width... 'defaultLineWidth'
109 endproc
111 ###############################################################
113 # Obligatory button Drawing Routines
115 # These MUST be defined
117 ###############################################################
119 procedure DrawRecord .color$ .x .y .size
120         .size /= 2
121     demo Paint circle... '.color$' '.x' '.y' '.size'
122 endproc
124 procedure DrawPlay .color$ .x .y .size
125         demo '.color$'
126         call drawTriangle 1 .x .y .size
127 endproc
129 procedure DrawQuit .color$ .x .y .size
130         demo Colour... '.color$'
131         .lineWidth = 0.5*.size**2
132         demo Line width... '.lineWidth'
133         .xstart = .x - .size
134         .ystart = .y + .size
135         .xend = .x + .size
136         .yend = .y - .size
137         demo Draw line... .xstart .ystart .xend .yend
138         .xstart = .x - .size
139         .ystart = .y - .size
140         .xend = .x + .size
141         .yend = .y + .size
142         demo Draw line... .xstart .ystart .xend .yend
143         demo Line width... 'defaultLineWidth'
144         demo Colour... Black
145 endproc
147 procedure DrawConfig .color$ .x .y .size
148         .size *= 1
149         .lineWidth = 0.4*.size
150         demo Arrow size... '.lineWidth'
151         .lineWidth = 0.4*.size**2
152         demo Line width... '.lineWidth'
153         .y += .size/2
154         .xstart = .x - .size
155         .xend = .x + .size
156         demo Draw arrow... .xstart .y .xend .y
157         demo Line width... 'defaultLineWidth'
158 endproc
160 procedure DrawRefresh .color$ .x .y .size
161         .lineWidth = 0.5*.size**2
162         .size /= 2
163         demo Line width... '.lineWidth'
164         demo Draw arc... '.x' '.y' '.size' 0 270
165         demo Line width... 'defaultLineWidth'
166 endproc
168 ###############################################################
170 # Button Processing Routines
172 ###############################################################
174 procedure processMainPageExample .clickX .clickY .pressed$
175         call generate_example
176 endproc
178 procedure processMainPagePrevious .clickX .clickY .pressed$
179         call clean_up_sound
180         call display_text Grey
181         te.currentWord -= 1
182         call init_window
183         # Draw the contour
184         call wipeArea 'wipeFeedbackArea$'
185         call display_text Black
186 endproc
188 procedure processMainPageNext .clickX .clickY .pressed$
189         call clean_up_sound
190         call display_text Grey
191         te.currentWord += 1
192         call init_window
193         # Draw the contour
194         call wipeArea 'wipeFeedbackArea$'
195         call display_text Black
196 endproc
198 procedure processMainPageWordlistUp .clickX .clickY .pressed$
199         call wipeArea 'wipeFeedbackArea$'
200     call load_word_list "'localWordlistDir$'" -1
201         call init_window
202         call display_text Black
203 endproc
205 procedure processMainPageWordlistDown .clickX .clickY .pressed$
206         call wipeArea 'wipeFeedbackArea$'
207     call load_word_list "'localWordlistDir$'" 1
208         call init_window
209         call display_text Black
210 endproc
212 ###############################################################
214 # Obligatory button Processing Routines
216 # These MUST be defined
218 ###############################################################
220 procedure processMainPageQuit .clickX .clickY .pressed$
221         call end_program
222 endproc
224 procedure processMainPageRefresh .clickX .clickY .pressed$
225         call init_window
226 endproc
228 procedure processMainPageConfig .clickX .clickY .pressed$
229         call config_page
230 endproc
232 procedure processMainPageHelp .clickX .clickY .pressed$
233         call help_loop 'buttons$' init_window
234 endproc
236 procedure processMainPagePlay .clickX .clickY .pressed$
237         call play_sound 'recordedSound$'
238 endproc
240 procedure processMainPageRecord .clickX .clickY .pressed$
241         call count_syllables
242         .recordingTime = recordingTime + ceiling((count_syllables.number - 2)/3)
243     call record_sound '.recordingTime'
244     call recognizeTone
246     # Wipe screen
247     call wipeArea 'wipeContourArea$'
248    
249     call draw_tone_contour
250     # Write text (again)
251     call display_word_list_name
252     call display_text Black
253         call add_feedback_to_toneevaluation Feedback
254     call write_feedback Feedback
255         select Table Feedback
256         Remove
257 endproc
260 ###############################################################
262 # Miscelaneous supporting code
264 ###############################################################
266 # The example
267 procedure generate_example
268         select Table 'wordlist$'
269         if te.currentWord > 0 and te.currentWord <= te.numberOfWords
270                 select Table 'wordlist$'
271                 .sound$ = Get value... 'te.currentWord' Sound
272                 .pinyin$ = Get value... 'te.currentWord' Pinyin
273                 if .sound$ = "-" or .sound$ = ""
274                         .sound$ = .pinyin$+".wav"
275                 endif
276                 .soundFilePath$ = localWordlistDir$+"/"+wordlistName$+"/"+.sound$
277                 .wordlistDirectory$ = ""
278                 if localWordlistDir$ <> "" and fileReadable("'localWordlistDir$'/'wordlistName$'")
279                         .wordlistDirectory$ = "'localWordlistDir$'/'wordlistName$'"
280                 elsif sgc2wordlists$ <> "" and fileReadable("'sgc2wordlists$'/'wordlistName$'")
281                         .wordlistDirectory$ = "'sgc2wordlists$'/'wordlistName$'"
282                 elsif globalwordlists$ <> "" and fileReadable("'globalwordlists$'/'wordlistName$'")
283                         .wordlistDirectory$ = "'globalwordlists$'/'wordlistName$'"
284                 endif
285                 if .wordlistDirectory$ <> ""
286                         .audioExampleList = Create Strings as file list... AudioList '.wordlistDirectory$'/'.pinyin$'.*
287                         .number_of_examples = Get number of strings
288                         if .number_of_examples > 0
289                                 Randomize
290                                 .sound$ = Get string... 1
291                                 .soundFilePath$ = "'.wordlistDirectory$'/'.sound$'"
292                         endif
293                         Remove
294                 endif
295                 if fileReadable(.soundFilePath$) and config.useSoundExample
296                         .tmp = -1
297                         .tmp = nocheck Read from file... '.soundFilePath$'
298                         if .tmp != undefined and .tmp > 0
299                                 Play
300                                 Remove
301                         endif
302                 elsif config.synthesis$ <> "" and config.synthesis$ <> "_DISABLED_"
303                         call synthesize_sound '.pinyin$'
304                 else
305                         call humToneContour '.pinyin$' 'config.register'
306                         call reset_viewport
307                 endif
308         endif
309         demoShow()
310 endproc
312 # Draw a tone contour
313 procedure draw_tone_contour
314         select Table 'wordlist$'
315         if te.currentWord > 0 and te.currentWord <= te.numberOfWords
316                 .sound$ = Get value... 'te.currentWord' Sound
317                 .pinyin$ = Get value... 'te.currentWord' Pinyin
318                 call drawToneContour '.pinyin$' 'config.register'
319                 call reset_viewport
320                 
321                 if te.recordedPitch > 0
322                         call drawSourceToneContour te.recordedPitch
323                 endif
324         endif
326 endproc
328 procedure recognizeTone
329         select Table 'wordlist$'
330         if te.currentWord > 0 and te.currentWord <= te.numberOfWords
331                 .sound$ = Get value... 'te.currentWord' Sound
332                 .pinyin$ = Get value... 'te.currentWord' Pinyin
333                 call align_recordedSound '.pinyin$'
334         call sgc_ToneProt 'recordedSound$' '.pinyin$' 'config.register' 'config.strict' 'config.language$'
335         # sgc_ToneProt manipulates the sound given. Reconnect
336         select Sound 'recordedSound$'
337         te.recordedSound = selected("Sound")
338                 call reset_viewport
339         endif
340 endproc
342 procedure write_feedback .table$
343     select Table '.table$'
344     .line1$ = Get value... 1 Text
345     .line2$ = Get value... 2 Text
346     .label$ = Get value... 3 Text
348         # convert numbers to Pinyin if needed
349         if not config.displayNumbers
350                 call numbers2pinyin '.line1$'
351                 .line1$ = numbers2pinyin.pinyin$
352         endif
354     .color$ = "Red"
355     if index(.line1$, "???") > 0
356         .color$ = "Black"
357     elsif .label$ = "Correct"
358         .color$ = "Green"
359         elsif config.strict
360                 .line2$ = .line2$ + " *"
361     endif
363         .currentFeedbackFontSize = 14
364         .maxHeight = 21 - 17
365         call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
366         .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
367         
368         call wipeArea 'wipeFeedbackArea$'
369     call set_font_size '.currentFeedbackFontSize'
370     demo '.color$'
371     demo Text... 50 Centre 21 Bottom '.line1$'
372     demo Text... 50 Centre 17 Bottom '.line2$'
373         demoShow()
374         demo 'defaultFont$'
375     call set_font_size 'defaultFontSize'
376     
377         # Log performance
378         .splitIndex = index(.line1$, ": ")
379         .pinyin$ = left$(.line1$, (.splitIndex - 1))
380         .choice$ = right$(.line1$, (length(.line1$) - .splitIndex - 1))
381         call log_performance 'recordedSound$' 'config.register' 'config.strict' '.pinyin$' '.choice$'
382 endproc
384 # Text display
385 procedure display_text .color$
386         select Table 'wordlist$'
387         if te.currentWord < 0 or te.currentWord > te.numberOfWords+1
388                 call clean_up_sound
389         if config.shuffleLists
390                     Randomize rows
391         endif
392                 if te.currentWord < 0
393                         te.currentWord = te.numberOfWords
394                 else
395                         te.currentWord = 1
396                 endif
397         endif
398         
399         if te.currentWord > 0 and te.currentWord <= te.numberOfWords
400                 .displayText$ = ""
401                 .displayPinyin$ = Get value... 'te.currentWord' Pinyin
402                 .displayChar$ = Get value... 'te.currentWord' Character
403                 .displayTrans$ = Get value... 'te.currentWord' Translation
404                 if .displayPinyin$ <> "-" and config.displayPinyin
405                         if not config.displayNumbers
406                                 call numbers2pinyin '.displayPinyin$'
407                                 .displayPinyin$ = numbers2pinyin.pinyin$
408                         endif
409                         # Insert u umlaut
410                         .displayPinyin$ = replace_regex$(.displayPinyin$, "v", "\\u\X22", 0)
411                         .displayText$ = .displayText$ + .displayPinyin$
412                 endif
413                 if .displayChar$ <> "-" and config.displayChar
414                         .displayText$ = .displayText$ + "  "+ .displayChar$
415                 endif
416                 if .displayTrans$ <> "-" and config.displayTrans
417                         .displayText$ = .displayText$ + "  \s{%%"+ .displayTrans$ + "%}"
418                 endif
419         elsif te.currentWord = 0 or te.currentWord = te.numberOfWords+1
420                 call clean_up_sound
421                 .displayText$ = "---"
422         endif
424         # Adapt font size
425         call adjustFontSizeOnHeight 'defaultFont$' 24 15
426         .currentFontSize = adjustFontSizeOnHeight.newFontSize
427         call adjustFontSizeOnWidth 'defaultFont$' '.currentFontSize' 95 '.displayText$'
428         .currentFontSize = adjustFontSizeOnWidth.newFontSize
430         # Clear the writing area
431         call wipeArea 'wipePinyinArea$'
432         # Actually display text
433         demo '.color$'
434         call set_font_size '.currentFontSize'
435         demo Text... 50 Centre 26 Bottom '.displayText$'
436         demoShow()
437         demo Black
438         demo 'defaultFont$'
439         call set_font_size 'defaultFontSize'
440 endproc
442 procedure numbers2pinyin .numberstext$
443         .intermediatePinyin$ = .numberstext$
444         # Move numbers to the nucleus vowel
445         # Tot he vowel
446         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([^aeuiov0-9]*)([0-9])", "\1\3\2", 0)
447         # Either a/e
448         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([ae])([aeuiov]*)([0-9])", "\1\3\2", 0)
449         # Or the Oo in /ou/
450         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(ou)([0-9])", "o\2u", 0)
451         # or the second vowel
452         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([uiov][aeuiov])([uiov])([0-9])", "\1\3\2", 0)
453         
454         # Convert all to special characters
455         # Tone 1
456         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a1", "ā", 0)
457         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e1", "ē", 0)
458         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u1", "ū", 0)
459         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i1", "ī", 0)
460         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o1", "ō", 0)
461         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v1", "ǖ", 0)
462         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "1", "\\-^", 0)
463         
464         # Tone 2
465         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v2", "ǘ", 0)
466         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])2", "\\\1'", 0)
467         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "2", "\\'^", 0)
468         
469         # Tone 3
470         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a3", "ǎ", 0)
471         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e3", "ě", 0)
472         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u3", "ǔ", 0)
473         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i3", "ǐ", 0)
474         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o3", "ǒ", 0)
475         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v3", "ǚ", 0)
476         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "3", "\\N^", 0)
478         # Tone 4
479         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v4", "ǜ", 0)
480         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])4", "\\\1`", 0)
481         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "4", "\\`^", 0)
482         
483         # Tone 0
484         # Remove tone 0 symbol completely
485         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "", 0)
486         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a0", "å", 0)
487         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e0", "e̊", 0)
488         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u0", "ů", 0)
489         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i0", "i̊", 0)
490         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o0", "o̊", 0)
491         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v0", "ü̊", 0)
492         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "\\0^", 0)
493         
494         # Pick best vowel symbols available in cases not caught before
495         # Ugly clutch to get the 1, 3, 0 tone diacritics at least in the neighbourhood
496         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i(\\[-N0]\^)", "i\\s{_ }\1", 0)
497         # Insert u umlaut
498         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v", "\\u\X22", 0)
500         .pinyin$ = .intermediatePinyin$
501 endproc
503 # NEEDS WORK AND TESTING!!
504 # Convert unicode Pinyin into tone numbers
505 procedure pinyin2numbers .pinyin$
506         .intermediatePinyin$ = .pinyin$
507         # Convert all special characters to numbers
508         # Tone 1
509         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ā([iaeouü]*)", "a\11", 0)
510         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ē([iaeouü]*)", "e\11", 0)
511         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ū([iaeouü]*)", "u\11", 0)
512         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ī([iaeouü]*)", "i\11", 0)
513         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ō([iaeouü]*)", "o\11", 0)
514         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǖ([iaeouü]*)", "v\11", 0)
515         
516         # Tone 2
517         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "á([iaeouü]*)", "a\12", 0)
518         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "é([iaeouü]*)", "e\12", 0)
519         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ú([iaeouü]*)", "u\12", 0)
520         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "í([iaeouü]*)", "i\12", 0)
521         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ó([iaeouü]*)", "o\12", 0)
522         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǘ([iaeouü]*)", "v\12", 0)
523         
524         # Tone 3
525         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǎ([iaeouü]*)", "a\13", 0)
526         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ě([iaeouü]*)", "e\13", 0)
527         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǔ([iaeouü]*)", "u\13", 0)
528         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǐ([iaeouü]*)", "i\13", 0)
529         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǒ([iaeouü]*)", "o\13", 0)
530         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǚ([iaeouü]*)", "v\13", 0)
532         # Tone 4
533         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "à([iaeouü]*)", "a\14", 0)
534         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "è([iaeouü]*)", "e\14", 0)
535         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ù([iaeouü]*)", "u\14", 0)
536         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ì([iaeouü]*)", "i\14", 0)
537         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ò([iaeouü]*)", "o\14", 0)
538         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǜ([iaeouü]*)", "v\14", 0)
539         
540         # Tone 0
541         # Add tone 0
542         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "å([iaeouü]*)", "a\10", 0)
543         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e̊([iaeouü]*)", "e\10", 0)
544         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ů([iaeouü]*)", "u\10", 0)
545         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i̊([iaeouü]*)", "i\10", 0)
546         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o̊([iaeouü]*)", "o\10", 0)
547         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ü̊([iaeouü]*)", "v\10", 0)
549         # Syllables without a tone symbol are tone 0
550         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov]+)([^0-9aeuiov]|$)", "\10\2", 0)
552         # Move numbers to the end of the syllable
553         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])((ng?)([^aeuiov]|$))?", "\1\3\2\4", 0)
554         
555         .numberstext$ = .intermediatePinyin$
556 endproc
558 # Includes
559 include ToneProt/SGC_ToneProt.praat
560 include ToneProt/DrawToneContour.praat
561 include ToneProt/HumToneContour.praat
562 include ToneProt/ToneRecognition.praat
563 include ToneProt/ToneScript.praat
564 include ToneProt/ToneRules.praat