Handling recording time
[sgc2.git] / MainPage.praat
blobd285cddb37255877384c36613c5bb939f35abcda
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         if count_syllables.number > 2
243                 .recordingTime = recordingTime + 1.0*ceiling((count_syllables.number - 2)/3)
244         endif
245     call record_sound '.recordingTime'
246     call recognizeTone
248     # Wipe screen
249     call wipeArea 'wipeContourArea$'
250    
251     call draw_tone_contour
252     # Write text (again)
253     call display_word_list_name
254     call display_text Black
255         call add_feedback_to_toneevaluation Feedback
256     call write_feedback Feedback
257         select Table Feedback
258         Remove
259 endproc
262 ###############################################################
264 # Miscelaneous supporting code
266 ###############################################################
268 # The example
269 procedure generate_example
270         select Table 'wordlist$'
271         if te.currentWord > 0 and te.currentWord <= te.numberOfWords
272                 select Table 'wordlist$'
273                 .sound$ = Get value... 'te.currentWord' Sound
274                 .pinyin$ = Get value... 'te.currentWord' Pinyin
275                 if .sound$ = "-" or .sound$ = ""
276                         .sound$ = .pinyin$+".wav"
277                 endif
278                 .soundFilePath$ = localWordlistDir$+"/"+wordlistName$+"/"+.sound$
279                 .wordlistDirectory$ = ""
280                 if localWordlistDir$ <> "" and fileReadable("'localWordlistDir$'/'wordlistName$'")
281                         .wordlistDirectory$ = "'localWordlistDir$'/'wordlistName$'"
282                 elsif sgc2wordlists$ <> "" and fileReadable("'sgc2wordlists$'/'wordlistName$'")
283                         .wordlistDirectory$ = "'sgc2wordlists$'/'wordlistName$'"
284                 elsif globalwordlists$ <> "" and fileReadable("'globalwordlists$'/'wordlistName$'")
285                         .wordlistDirectory$ = "'globalwordlists$'/'wordlistName$'"
286                 endif
287                 if .wordlistDirectory$ <> ""
288                         .audioExampleList = Create Strings as file list... AudioList '.wordlistDirectory$'/'.pinyin$'.*
289                         .number_of_examples = Get number of strings
290                         if .number_of_examples > 0
291                                 Randomize
292                                 .sound$ = Get string... 1
293                                 .soundFilePath$ = "'.wordlistDirectory$'/'.sound$'"
294                         endif
295                         Remove
296                 endif
297                 if fileReadable(.soundFilePath$) and config.useSoundExample
298                         .tmp = -1
299                         .tmp = nocheck Read from file... '.soundFilePath$'
300                         if .tmp != undefined and .tmp > 0
301                                 Play
302                                 Remove
303                         endif
304                 elsif config.synthesis$ <> "" and config.synthesis$ <> "_DISABLED_"
305                         call synthesize_sound '.pinyin$'
306                 else
307                         call humToneContour '.pinyin$' 'config.register'
308                         call reset_viewport
309                 endif
310         endif
311         demoShow()
312 endproc
314 # Draw a tone contour
315 procedure draw_tone_contour
316         select Table 'wordlist$'
317         if te.currentWord > 0 and te.currentWord <= te.numberOfWords
318                 .sound$ = Get value... 'te.currentWord' Sound
319                 .pinyin$ = Get value... 'te.currentWord' Pinyin
320                 call drawToneContour '.pinyin$' 'config.register'
321                 call reset_viewport
322                 
323                 if te.recordedPitch > 0
324                         call drawSourceToneContour te.recordedPitch
325                 endif
326         endif
328 endproc
330 procedure recognizeTone
331         select Table 'wordlist$'
332         if te.currentWord > 0 and te.currentWord <= te.numberOfWords
333                 .sound$ = Get value... 'te.currentWord' Sound
334                 .pinyin$ = Get value... 'te.currentWord' Pinyin
335                 call align_recordedSound '.pinyin$'
336         call sgc_ToneProt 'recordedSound$' '.pinyin$' 'config.register' 'config.strict' 'config.language$'
337         # sgc_ToneProt manipulates the sound given. Reconnect
338         select Sound 'recordedSound$'
339         te.recordedSound = selected("Sound")
340                 call reset_viewport
341         endif
342 endproc
344 procedure write_feedback .table$
345     select Table '.table$'
346     .line1$ = Get value... 1 Text
347     .line2$ = Get value... 2 Text
348     .label$ = Get value... 3 Text
350         # convert numbers to Pinyin if needed
351         if not config.displayNumbers
352                 call numbers2pinyin '.line1$'
353                 .line1$ = numbers2pinyin.pinyin$
354         endif
356     .color$ = "Red"
357     if index(.line1$, "???") > 0
358         .color$ = "Black"
359     elsif .label$ = "Correct"
360         .color$ = "Green"
361         elsif config.strict
362                 .line2$ = .line2$ + " *"
363     endif
365         .currentFeedbackFontSize = 14
366         .maxHeight = 21 - 17
367         call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
368         .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
369         
370         call wipeArea 'wipeFeedbackArea$'
371     call set_font_size '.currentFeedbackFontSize'
372     demo '.color$'
373     demo Text... 50 Centre 21 Bottom '.line1$'
374     demo Text... 50 Centre 17 Bottom '.line2$'
375         demoShow()
376         demo 'defaultFont$'
377     call set_font_size 'defaultFontSize'
378     
379         # Log performance
380         .splitIndex = index(.line1$, ": ")
381         .pinyin$ = left$(.line1$, (.splitIndex - 1))
382         .choice$ = right$(.line1$, (length(.line1$) - .splitIndex - 1))
383         call log_performance 'recordedSound$' 'config.register' 'config.strict' '.pinyin$' '.choice$'
384 endproc
386 # Text display
387 procedure display_text .color$
388         select Table 'wordlist$'
389         if te.currentWord < 0 or te.currentWord > te.numberOfWords+1
390                 call clean_up_sound
391         if config.shuffleLists
392                     Randomize rows
393         endif
394                 if te.currentWord < 0
395                         te.currentWord = te.numberOfWords
396                 else
397                         te.currentWord = 1
398                 endif
399         endif
400         
401         if te.currentWord > 0 and te.currentWord <= te.numberOfWords
402                 .displayText$ = ""
403                 .displayPinyin$ = Get value... 'te.currentWord' Pinyin
404                 .displayChar$ = Get value... 'te.currentWord' Character
405                 .displayTrans$ = Get value... 'te.currentWord' Translation
406                 if .displayPinyin$ <> "-" and config.displayPinyin
407                         if not config.displayNumbers
408                                 call numbers2pinyin '.displayPinyin$'
409                                 .displayPinyin$ = numbers2pinyin.pinyin$
410                         endif
411                         # Insert u umlaut
412                         .displayPinyin$ = replace_regex$(.displayPinyin$, "v", "\\u\X22", 0)
413                         .displayText$ = .displayText$ + .displayPinyin$
414                 endif
415                 if .displayChar$ <> "-" and config.displayChar
416                         .displayText$ = .displayText$ + "  "+ .displayChar$
417                 endif
418                 if .displayTrans$ <> "-" and config.displayTrans
419                         .displayText$ = .displayText$ + "  \s{%%"+ .displayTrans$ + "%}"
420                 endif
421         elsif te.currentWord = 0 or te.currentWord = te.numberOfWords+1
422                 call clean_up_sound
423                 .displayText$ = "---"
424         endif
426         # Adapt font size
427         call adjustFontSizeOnHeight 'defaultFont$' 24 15
428         .currentFontSize = adjustFontSizeOnHeight.newFontSize
429         call adjustFontSizeOnWidth 'defaultFont$' '.currentFontSize' 95 '.displayText$'
430         .currentFontSize = adjustFontSizeOnWidth.newFontSize
432         # Clear the writing area
433         call wipeArea 'wipePinyinArea$'
434         # Actually display text
435         demo '.color$'
436         call set_font_size '.currentFontSize'
437         demo Text... 50 Centre 26 Bottom '.displayText$'
438         demoShow()
439         demo Black
440         demo 'defaultFont$'
441         call set_font_size 'defaultFontSize'
442 endproc
444 procedure numbers2pinyin .numberstext$
445         .intermediatePinyin$ = .numberstext$
446         # Move numbers to the nucleus vowel
447         # Tot he vowel
448         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([^aeuiov0-9]*)([0-9])", "\1\3\2", 0)
449         # Either a/e
450         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([ae])([aeuiov]*)([0-9])", "\1\3\2", 0)
451         # Or the Oo in /ou/
452         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(ou)([0-9])", "o\2u", 0)
453         # or the second vowel
454         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([uiov][aeuiov])([uiov])([0-9])", "\1\3\2", 0)
455         
456         # Convert all to special characters
457         # Tone 1
458         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a1", "ā", 0)
459         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e1", "ē", 0)
460         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u1", "ū", 0)
461         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i1", "ī", 0)
462         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o1", "ō", 0)
463         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v1", "ǖ", 0)
464         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "1", "\\-^", 0)
465         
466         # Tone 2
467         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v2", "ǘ", 0)
468         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])2", "\\\1'", 0)
469         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "2", "\\'^", 0)
470         
471         # Tone 3
472         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a3", "ǎ", 0)
473         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e3", "ě", 0)
474         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u3", "ǔ", 0)
475         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i3", "ǐ", 0)
476         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o3", "ǒ", 0)
477         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v3", "ǚ", 0)
478         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "3", "\\N^", 0)
480         # Tone 4
481         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v4", "ǜ", 0)
482         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])4", "\\\1`", 0)
483         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "4", "\\`^", 0)
484         
485         # Tone 0
486         # Remove tone 0 symbol completely
487         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "", 0)
488         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a0", "å", 0)
489         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e0", "e̊", 0)
490         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u0", "ů", 0)
491         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i0", "i̊", 0)
492         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o0", "o̊", 0)
493         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v0", "ü̊", 0)
494         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "\\0^", 0)
495         
496         # Pick best vowel symbols available in cases not caught before
497         # Ugly clutch to get the 1, 3, 0 tone diacritics at least in the neighbourhood
498         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i(\\[-N0]\^)", "i\\s{_ }\1", 0)
499         # Insert u umlaut
500         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v", "\\u\X22", 0)
502         .pinyin$ = .intermediatePinyin$
503 endproc
505 # NEEDS WORK AND TESTING!!
506 # Convert unicode Pinyin into tone numbers
507 procedure pinyin2numbers .pinyin$
508         .intermediatePinyin$ = .pinyin$
509         # Convert all special characters to numbers
510         # Tone 1
511         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ā([iaeouü]*)", "a\11", 0)
512         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ē([iaeouü]*)", "e\11", 0)
513         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ū([iaeouü]*)", "u\11", 0)
514         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ī([iaeouü]*)", "i\11", 0)
515         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ō([iaeouü]*)", "o\11", 0)
516         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǖ([iaeouü]*)", "v\11", 0)
517         
518         # Tone 2
519         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "á([iaeouü]*)", "a\12", 0)
520         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "é([iaeouü]*)", "e\12", 0)
521         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ú([iaeouü]*)", "u\12", 0)
522         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "í([iaeouü]*)", "i\12", 0)
523         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ó([iaeouü]*)", "o\12", 0)
524         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǘ([iaeouü]*)", "v\12", 0)
525         
526         # Tone 3
527         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǎ([iaeouü]*)", "a\13", 0)
528         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ě([iaeouü]*)", "e\13", 0)
529         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǔ([iaeouü]*)", "u\13", 0)
530         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǐ([iaeouü]*)", "i\13", 0)
531         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǒ([iaeouü]*)", "o\13", 0)
532         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǚ([iaeouü]*)", "v\13", 0)
534         # Tone 4
535         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "à([iaeouü]*)", "a\14", 0)
536         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "è([iaeouü]*)", "e\14", 0)
537         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ù([iaeouü]*)", "u\14", 0)
538         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ì([iaeouü]*)", "i\14", 0)
539         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ò([iaeouü]*)", "o\14", 0)
540         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ǜ([iaeouü]*)", "v\14", 0)
541         
542         # Tone 0
543         # Add tone 0
544         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "å([iaeouü]*)", "a\10", 0)
545         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e̊([iaeouü]*)", "e\10", 0)
546         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ů([iaeouü]*)", "u\10", 0)
547         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i̊([iaeouü]*)", "i\10", 0)
548         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o̊([iaeouü]*)", "o\10", 0)
549         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ü̊([iaeouü]*)", "v\10", 0)
551         # Syllables without a tone symbol are tone 0
552         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov]+)([^0-9aeuiov]|$)", "\10\2", 0)
554         # Move numbers to the end of the syllable
555         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])((ng?)([^aeuiov]|$))?", "\1\3\2\4", 0)
556         
557         .numberstext$ = .intermediatePinyin$
558 endproc
560 # Includes
561 include ToneProt/SGC_ToneProt.praat
562 include ToneProt/DrawToneContour.praat
563 include ToneProt/HumToneContour.praat
564 include ToneProt/ToneRecognition.praat
565 include ToneProt/ToneScript.praat
566 include ToneProt/ToneRules.praat