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.
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
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.
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.
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
28 # Includes at the bottom
30 ###############################################################
32 # Button Drawing Routines
34 ###############################################################
36 procedure DrawPrevious .color$ .x .y .size
39 call drawTriangle -1 .x .y .size
40 .currentX = drawTriangle.currentX
41 .endX = .currentX - 0.5
44 demo Paint rectangle... '.color$' '.currentX' '.endX' '.lowY' '.highY'
47 procedure DrawNext .color$ .x .y .size
50 call drawTriangle 1 .x .y .size
51 .currentX = drawTriangle.currentX
52 .endX = .currentX + 0.5
55 demo Paint rectangle... '.color$' '.currentX' '.endX' '.lowY' '.highY'
58 procedure DrawSelectWords .color$ .x .y .size
62 call adjustFontSizeOnHeight 'defaultFont$' '.currentFontSize' '.maxHeight'
63 .currentFontSize = adjustFontSizeOnHeight.currentFontSize
64 call set_font_size '.currentFontSize'
65 demo Colour... '.color$'
66 demo Text... '.x' Centre '.y' Bottom ...
67 call set_font_size 'defaultFontSize'
70 procedure DrawWordListUp .color$ .x .y .size
79 demo Draw line... .xleft .ylow .xmidleft .yhigh
80 demo Draw line... .xright .ylow .xmidright .yhigh
81 demo Line width... 'defaultLineWidth'
85 procedure DrawWordListDown .color$ .x .y .size
94 demo Draw line... .xleft .yhigh .xmidleft .ylow
95 demo Draw line... .xright .yhigh .xmidright .ylow
96 demo Line width... 'defaultLineWidth'
100 procedure drawTriangle .direction .x .y .size
101 # Make sure direction = +/- 1
105 .direction /= abs(.direction)
108 .currentHeight = .size
109 .currentX = .x - .direction*.size
111 demo Line width... 2.0
113 while .currentHeight> 0
114 .ystart = .y + .currentHeight
115 .yend = .y - .currentHeight
116 demo Draw line... .currentX .ystart .currentX .yend
117 .currentHeight -= .offset *3/4
118 .currentX += .direction*.offset * 1.5
120 demo Line width... 'defaultLineWidth'
123 ###############################################################
125 # Obligatory button Drawing Routines
127 # These MUST be defined
129 ###############################################################
131 procedure DrawRecord .color$ .x .y .size
133 demo Paint circle... '.color$' '.x' '.y' '.size'
136 procedure DrawPlay .color$ .x .y .size
138 call drawTriangle 1 .x .y .size
141 procedure DrawQuit .color$ .x .y .size
142 demo Colour... '.color$'
143 .lineWidth = 0.5*.size**2
144 demo Line width... '.lineWidth'
149 demo Draw line... .xstart .ystart .xend .yend
154 demo Draw line... .xstart .ystart .xend .yend
155 demo Line width... 'defaultLineWidth'
159 procedure DrawConfig .color$ .x .y .size
161 .lineWidth = 0.4*.size
162 demo Arrow size... '.lineWidth'
163 .lineWidth = 0.4*.size**2
164 demo Line width... '.lineWidth'
168 demo Draw arrow... .xstart .y .xend .y
169 demo Line width... 'defaultLineWidth'
172 procedure DrawRefresh .color$ .x .y .size
173 .lineWidth = 0.5*.size**2
175 demo Line width... '.lineWidth'
176 demo Draw arc... '.x' '.y' '.size' 0 270
177 demo Line width... 'defaultLineWidth'
180 ###############################################################
182 # Button Processing Routines
184 ###############################################################
186 procedure processMainPageExample .clickX .clickY .pressed$
187 call generate_example
190 procedure processMainPagePrevious .clickX .clickY .pressed$
192 call display_text Grey
195 call wipeArea 'wipeFeedbackArea$'
197 call display_text Black
199 sgc.failedAttempts = 0
202 procedure processMainPageNext .clickX .clickY .pressed$
204 call display_text Grey
206 call wipeArea 'wipeFeedbackArea$'
209 call display_text Black
212 procedure processMainPageWordlistUp .clickX .clickY .pressed$
213 call wipeArea 'wipeFeedbackArea$'
214 call load_word_list "'localWordlistDir$'" -1
216 call display_text Black
219 procedure processMainPageWordlistDown .clickX .clickY .pressed$
220 call wipeArea 'wipeFeedbackArea$'
221 call load_word_list "'localWordlistDir$'" 1
223 call display_text Black
226 procedure processMainPageGRADE .clickX .clickY .pressed$
227 call setGrade '.pressed$'
232 procedure processMainPagePinYinArea .clickX .clickY .pressed$
235 call display_text Red
239 # Select the words to practise. This is quite a complex piece of code
240 procedure processMainPageSelectWords .clickX .clickY .pressed$
242 .label$ = "SelectWords"
243 call Draw_button '.table$' '.label$' 1
246 call findLabel '.table$' '.label$'
248 select Table '.table$'
249 .helpText$ = Get value... '.row' Helptext
250 call convert_praat_to_latin1 '.helpText$'
251 .helpText$ = convert_praat_to_latin1.text$
254 select Table 'wordlist$'
255 .tmpOriginalWordlist = Copy: "Original_'wordlist$'"
259 select Table 'wordlist$'
260 sgc.numberOfWords = Get number of rows
261 .currentWord = sgc.currentWord
262 if .currentWord <= 0 or .currentWord > sgc.numberOfWords or config.shuffleLists
267 call get_feedback_text 'config.language$' Part
268 call convert_praat_to_latin1 'get_feedback_text.text$'
269 .partText$ = convert_praat_to_latin1.text$
270 call get_feedback_text 'config.language$' Tones
271 call convert_praat_to_latin1 'get_feedback_text.text$'
272 .toneText$ = convert_praat_to_latin1.text$
273 call get_feedback_text 'config.language$' Cancel
274 call convert_praat_to_latin1 'get_feedback_text.text$'
275 .cancelText$ = convert_praat_to_latin1.text$
276 call get_feedback_text 'config.language$' Clear
277 call convert_praat_to_latin1 'get_feedback_text.text$'
278 .clearText$ = convert_praat_to_latin1.text$
279 call get_feedback_text 'config.language$' All
280 call convert_praat_to_latin1 'get_feedback_text.text$'
281 .allText$ = convert_praat_to_latin1.text$
282 call get_feedback_text 'config.language$' Previous
283 call convert_praat_to_latin1 'get_feedback_text.text$'
284 .prevWord$ = convert_praat_to_latin1.text$
285 call get_feedback_text 'config.language$' Next
286 call convert_praat_to_latin1 'get_feedback_text.text$'
287 .nextWord$ = convert_praat_to_latin1.text$
288 call get_feedback_text 'config.language$' Continue
289 call convert_praat_to_latin1 'get_feedback_text.text$'
290 .continueText$ = convert_praat_to_latin1.text$
291 call get_feedback_text 'config.language$' Show
292 call convert_praat_to_latin1 'get_feedback_text.text$'
293 .showText$ = convert_praat_to_latin1.text$
295 .pinyinText$ = "Pinyin"
296 .characterText$ = "Character"
299 select Table 'wordlist$'
300 .lessonCol = Get column index: "Lesson"
303 # All shown keeps track whether all words are shown
304 # If so, selecting a lesson is preceded by a Clear All
306 # Sort words for consistent selection interface
307 if config.shuffleLists
308 # Allow subdivision in lessons
310 Sort rows... Lesson Pinyin
316 for .i to sgc.numberOfWords
317 .currentLesson$ = Get value: .i, "Lesson"
318 if .currentLesson$ <> "" and .currentLesson$ <> "-" and index_regex(.lessonList$, "\t'.currentLesson$'\t") <= 0
319 .lessonList$ = .lessonList$ + .currentLesson$ + tab$
321 .lessonName$['.numLessons'] = .currentLesson$
323 .shown$ = Get value: .i, "Show"
331 .numWordsPerScreen = 15
332 while clicked <> 6 and clicked <> 1
337 select Table 'wordlist$'
338 .lessonCol = Get column index: "Lesson"
339 # Sort words for consistent selection interface
340 if config.shuffleLists
341 # Allow subdivision in lessons
343 Sort rows... Lesson Pinyin
348 .max = .numWordsPerScreen - 1
349 if .currentWord + .max > sgc.numberOfWords
350 .max = sgc.numberOfWords - .currentWord
352 for .i from 0 to .numWordsPerScreen - 1
354 .currentPinyin$ = Get value: .currentWord+.i, "Pinyin"
355 if index_regex(.currentPinyin$, "[0-9]") <= 0
356 call pinyin2numbers '.currentPinyin$'
357 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
358 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
360 .pinyin$[.i] = .currentPinyin$
362 .character$[.i] = Get value: .currentWord+.i, "Character"
365 .lessonNum$[.i] = Get value: .currentWord+.i, "Lesson"
366 .lessonNum$[.i] = " : " + .lessonNum$[.i]
368 .showText$[.i] = .pinyin$['.i']
369 if .character$['.i'] <> "-"
370 .showText$[.i] = .pinyin$['.i']+" ("+.character$['.i']+.lessonNum$['.i']+")"
371 elsif .lessonNum$['.i'] <> ""
372 .showText$[.i] = .pinyin$['.i']+" ( -"+.lessonNum$['.i']+")"
374 .showValueText$[.i] = Get value: .currentWord+.i, "Show"
375 if .showValueText$[.i] = "-"
380 .showVariable$[.i] = .pinyin$[.i]
381 .tmp$ = .showVariable$[.i]
382 '.tmp$' = .showValue[.i]
389 # The user text input window (beginPause .... endPause)
390 beginPause(.helpText$)
391 boolean (.showText$[0], .showValue[0])
392 boolean (.showText$[1], .showValue[1])
393 boolean (.showText$[2], .showValue[2])
394 boolean (.showText$[3], .showValue[3])
395 boolean (.showText$[4], .showValue[4])
396 boolean (.showText$[5], .showValue[5])
397 boolean (.showText$[6], .showValue[6])
398 boolean (.showText$[7], .showValue[7])
399 boolean (.showText$[8], .showValue[8])
400 boolean (.showText$[9], .showValue[9])
401 boolean (.showText$[10], .showValue[10])
402 boolean (.showText$[11], .showValue[11])
403 boolean (.showText$[12], .showValue[12])
404 boolean (.showText$[13], .showValue[13])
405 boolean (.showText$[14], .showValue[14])
407 optionMenu: .partText$, 1
410 for .j to .numLessons
411 option: .lessonName$['.j']
414 optionMenu: .toneText$, 1
421 clicked = endPause ("'.cancelText$'", "'.clearText$'", "'.allText$'", "'.prevWord$'", "'.nextWord$'", "'.continueText$'", 6, 1)
424 for .i to sgc.numberOfWords
425 Set string value: .i, "Show", "-"
429 for .i to sgc.numberOfWords
430 Set string value: .i, "Show", "+"
434 # Get selected Part BEFORE we do anything else
436 .tmp$ = replace_regex$(.partText$, "^(.)", "\l\1", 0)
437 .lessonSelected = '.tmp$' - 1
439 if .lessonSelected > 0
442 select Table 'wordlist$'
443 for .i to sgc.numberOfWords
444 # Keep track of whether all are shown
445 .shown$ = Get value: .i, "Show"
450 for .i to sgc.numberOfWords
452 .currentLesson$ = Get value: .i, "Lesson"
453 if .currentLesson$ = .lessonName$['.lessonSelected']
454 Set string value: .i, "Show", "+"
456 Set string value: .i, "Show", "-"
459 for .i to sgc.numberOfWords
460 # Keep track of whether all are shown
461 .shown$ = Get value: .i, "Show"
462 if .firstShown <=0 and .shown$ <> "-"
467 for .i from 0 to .max
468 .tmp$ = .showVariable$['.i']
469 .showValue['.i'] = '.tmp$'
470 .showWord$['.i'] = "-"
471 if .showValue['.i'] <> 0
472 .showWord$['.i'] = "+"
474 Set string value: .currentWord+.i, "Show", .showWord$['.i']
477 .tmp$ = replace_regex$(.toneText$, "^(.)", "\l\1", 0)
478 .toneSelected = '.tmp$' - 2
479 if .toneSelected >= 0
480 select Table 'wordlist$'
481 for .i to sgc.numberOfWords
482 .currentPinyin$ = Get value: .i, "Pinyin"
483 if index_regex(.currentPinyin$, "[0-9]") <= 0
484 call pinyin2numbers '.currentPinyin$'
485 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
486 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
488 .tmp$ = Get value: .i, "Show"
489 if .tmp$ <> "-" and index(.currentPinyin$, "'.toneSelected'") > 0
490 Set string value: .i, "Show", "+"
492 Set string value: .i, "Show", "-"
500 .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
501 elsif .toneSelected < 0
502 .currentWord -= .numWordsPerScreen
505 .currentWord = (sgc.numberOfWords div .numWordsPerScreen) * .numWordsPerScreen + 1
509 .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
510 elsif .toneSelected < 0
511 .currentWord += .numWordsPerScreen
513 if .currentWord > sgc.numberOfWords
518 # Reset and go to the first selected word (can shuffle list)
527 select Table 'wordlist$'
529 select .tmpOriginalWordlist
532 select .tmpOriginalWordlist
534 call Draw_button '.table$' '.label$' 0
537 ###############################################################
539 # Obligatory button Processing Routines
541 # These MUST be defined
543 ###############################################################
545 procedure processMainPageQuit .clickX .clickY .pressed$
549 procedure processMainPageRefresh .clickX .clickY .pressed$
554 procedure processMainPageConfig .clickX .clickY .pressed$
558 procedure processMainPageHelp .clickX .clickY .pressed$
559 call help_loop 'buttons$' init_window
562 procedure processMainPagePlay .clickX .clickY .pressed$
565 if recordedSound$ <> ""
566 call play_sound 'sgc.recordedSound'
569 te.buttonPressValue = mainPage.play
572 procedure Set_Play_Button
574 if recordedSound$ <> ""
577 call Draw_button MainPage Play 'mainPage.play'
580 procedure processMainPageRecord .clickX .clickY .pressed$
582 .recordingTime = recordingTime
583 if count_syllables.number > 2
584 .recordingTime = recordingTime + 1.0*ceiling((count_syllables.number - 2)/2)
586 call record_sound '.recordingTime'
592 call wipeArea 'wipeContourArea$'
594 call draw_tone_contour
596 call display_word_list_name
597 call display_text Black
598 call add_feedback_to_toneevaluation Feedback
599 call write_feedback Feedback
600 select Table Feedback
603 # Do not exercise words that are going well (autoSelect)
604 if add_feedback_to_toneevaluation.result > 0
605 if config.adaptiveLists > 0 and sgc.failedAttempts < 2
606 # Deselect current word
607 select Table 'wordlist$'
608 .i = Search column: "Pinyin", sgc.pinyin$
610 Set string value: .i, "Show", "-"
613 sgc.failedAttempts = 0
615 sgc.failedAttempts += 1
620 ###############################################################
622 # Miscelaneous supporting code
624 ###############################################################
627 procedure generate_example
628 select Table 'wordlist$'
629 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
630 select Table 'wordlist$'
631 .sound$ = Get value... 'sgc.currentWord' Sound
632 call readPinyin 'sgc.currentWord'
633 sgc.pinyin$ = readPinyin.pinyin$
634 if .sound$ = "-" or .sound$ = ""
635 .sound$ = sgc.pinyin$+".wav"
637 .soundFilePath$ = localWordlistDir$+"/"+wordlistName$+"/"+.sound$
638 .wordlistDirectory$ = ""
639 if localWordlistDir$ <> "" and fileReadable("'localWordlistDir$'/'wordlistName$'")
640 .wordlistDirectory$ = "'localWordlistDir$'/'wordlistName$'"
641 elsif sgc2wordlists$ <> "" and fileReadable("'sgc2wordlists$'/'wordlistName$'")
642 .wordlistDirectory$ = "'sgc2wordlists$'/'wordlistName$'"
643 elsif globalwordlists$ <> "" and fileReadable("'globalwordlists$'/'wordlistName$'")
644 .wordlistDirectory$ = "'globalwordlists$'/'wordlistName$'"
646 if .wordlistDirectory$ <> ""
647 .audioExampleList = Create Strings as file list... AudioList '.wordlistDirectory$'/'sgc.pinyin$'.*
648 .number_of_examples = Get number of strings
649 if .number_of_examples > 0
651 .sound$ = Get string... 1
652 .soundFilePath$ = "'.wordlistDirectory$'/'.sound$'"
656 if fileReadable(.soundFilePath$) and config.useSoundExample
658 .tmp = nocheck Read from file... '.soundFilePath$'
659 if .tmp != undefined and .tmp > 0
660 call play_sound '.tmp'
664 elsif config.synthesis$ <> "" and config.synthesis$ <> "_DISABLED_"
665 call synthesize_sound 'sgc.pinyin$'
667 call humToneContour 'sgc.pinyin$' 'config.register'
674 # Draw a tone contour
675 procedure draw_tone_contour
676 select Table 'wordlist$'
677 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
678 .sound$ = Get value... 'sgc.currentWord' Sound
679 call readPinyin 'sgc.currentWord'
680 sgc.pinyin$ = readPinyin.pinyin$
681 call drawToneContour 'sgc.pinyin$' 'config.register'
684 if te.recordedPitch > 0
685 call drawSourceToneContour te.recordedPitch
691 procedure recognizeTone
692 select Table 'wordlist$'
693 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
695 if index_regex(config.strict$, "[^0-9]") <= 0
696 .strict = ('config.strict$' >= sgc.highestLevel)
699 .sound$ = Get value... 'sgc.currentWord' Sound
700 call readPinyin 'sgc.currentWord'
701 sgc.pinyin$ = readPinyin.pinyin$
702 call align_recordedSound 'sgc.pinyin$'
703 call sgc_ToneProt 'recordedSound$' 'sgc.pinyin$' 'config.register' '.strict' 'config.language$'
704 # sgc_ToneProt manipulates the sound given. Reconnect
705 select Sound 'recordedSound$'
706 sgc.recordedSound = selected("Sound")
711 procedure write_feedback .table$
712 select Table '.table$'
713 .line1$ = Get value... 1 Text
714 .line2$ = Get value... 2 Text
715 .label$ = Get value... 3 Text
717 # convert numbers to Pinyin if needed
718 if not config.displayNumbers
719 call numbers2pinyin '.line1$'
720 .line1$ = numbers2pinyin.pinyin$
724 if index(.line1$, "???") > 0
726 elsif .label$ = "Correct"
728 elsif config.strict$ = "'sgc.highestLevel'"
729 .line2$ = .line2$ + " *"
732 .currentFeedbackFontSize = 14
734 call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
735 .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
737 call wipeArea 'wipeFeedbackArea$'
738 call set_font_size '.currentFeedbackFontSize'
740 demo Text... 50 Centre 21 Bottom '.line1$'
741 demo Text... 50 Centre 17 Bottom '.line2$'
744 call set_font_size 'defaultFontSize'
748 procedure display_text .color$
749 select Table 'wordlist$'
750 if sgc.currentWord < 0 or sgc.currentWord > sgc.numberOfWords+1
752 if config.shuffleLists
755 if sgc.currentWord < 0
756 sgc.currentWord = sgc.numberOfWords
763 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
765 call readDisplayPinyin 'sgc.currentWord'
766 .displayPinyin$ = readDisplayPinyin.pinyin$
767 .displayChar$ = Get value... 'sgc.currentWord' Character
768 .displayTrans$ = Get value... 'sgc.currentWord' Translation
769 if .displayPinyin$ <> "-" and (config.displayPinyin or sgc.writeAll)
770 if not config.displayNumbers
771 call numbers2pinyin '.displayPinyin$'
772 .displayPinyin$ = numbers2pinyin.pinyin$
775 .displayPinyin$ = replace_regex$(.displayPinyin$, "v", "\\u\X22", 0)
776 .displayText$ = .displayText$ + .displayPinyin$
778 if .displayChar$ <> "-" and (config.displayChar or sgc.writeAll)
779 .displayText$ = .displayText$ + " "+ .displayChar$
782 if .displayTrans$ <> "-" and (config.displayTrans or sgc.writeAll)
783 .displayText$ = .displayText$ + " \s{%%"+ .displayTrans$ + "%}"
785 elsif sgc.currentWord = 0 or sgc.currentWord = sgc.numberOfWords+1
787 .displayText$ = "---"
791 call adjustFontSizeOnHeight 'defaultFont$' 24 15
792 .currentFontSize = adjustFontSizeOnHeight.newFontSize
793 call adjustFontSizeOnWidth 'defaultFont$' '.currentFontSize' 95 '.displayText$'
794 .currentFontSize = adjustFontSizeOnWidth.newFontSize
796 # Clear the writing area
797 call wipeArea 'wipePinyinArea$'
798 # Switch back to Chinese style CJK when in Japanese language mode
799 if .changeCJKstyle and config.language$ = "JA"
800 CJK font style preferences: "Chinese"
802 # Actually display text
804 call set_font_size '.currentFontSize'
805 demo Text... 50 Centre 26 Bottom '.displayText$'
809 call set_font_size 'defaultFontSize'
810 if .changeCJKstyle and config.language$ = "JA"
811 if config.language$ = "JA"
812 CJK font style preferences: "Japanese"
813 elsif config.language$ = "ZH"
814 CJK font style preferences: "Chinese"
817 # Switch back to Japanese style CJK when in Japanese language mode
818 if .changeCJKstyle and config.language$ = "JA"
819 CJK font style preferences: "Japanese"
823 procedure numbers2pinyin .numberstext$
824 .intermediatePinyin$ = .numberstext$
825 # Add a `-quote between vowels
826 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])([aeuiov])", "\1\2'\3", 0)
827 # Move numbers to the nucleus vowel
829 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([^aeuiov0-9]*)([0-9])", "\1\3\2", 0)
831 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([ae])([aeuiov]*)([0-9])", "\1\3\2", 0)
833 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(ou)([0-9])", "o\2u", 0)
834 # or the second vowel
835 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([uiov][aeuiov])([uiov])([0-9])", "\1\3\2", 0)
837 # Convert all tones to special characters
839 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a1", "ā", 0)
840 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e1", "ē", 0)
841 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u1", "ū", 0)
842 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i1", "ī", 0)
843 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o1", "ō", 0)
844 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v1", "ǖ", 0)
845 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "1", "\\-^", 0)
848 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v2", "ǘ", 0)
849 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])2", "\\\1'", 0)
850 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "2", "\\'^", 0)
853 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a3", "ǎ", 0)
854 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e3", "ě", 0)
855 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u3", "ǔ", 0)
856 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i3", "ǐ", 0)
857 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o3", "ǒ", 0)
858 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v3", "ǚ", 0)
859 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "3", "\\N^", 0)
862 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v4", "ǜ", 0)
863 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])4", "\\\1`", 0)
864 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "4", "\\`^", 0)
867 # Remove tone 0 symbol completely
868 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "", 0)
869 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a0", "å", 0)
870 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e0", "e̊", 0)
871 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u0", "ů", 0)
872 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i0", "i̊", 0)
873 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o0", "o̊", 0)
874 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v0", "ü̊", 0)
875 #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "\\0^", 0)
877 # Pick best vowel symbols available in cases not caught before
878 # Ugly clutch to get the 1, 3, 0 tone diacritics at least in the neighbourhood
879 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i(\\[-N0]\^)", "i\\s{_ }\1", 0)
881 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v", "\\u\X22", 0)
883 .pinyin$ = .intermediatePinyin$
886 # NEEDS WORK AND TESTING!!
887 # Convert unicode Pinyin into tone numbers
888 procedure pinyin2numbers .pinyin$
889 .intermediatePinyin$ = .pinyin$
890 # Convert all special characters to numbers
892 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iā)([iaeouü]*)", "a\11", 0)
893 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iē)([iaeouü]*)", "e\11", 0)
894 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iū)([iaeouü]*)", "u\11", 0)
895 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iī)([iaeouü]*)", "i\11", 0)
896 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iō)([iaeouü]*)", "o\11", 0)
897 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǖ)([iaeouü]*)", "v\11", 0)
900 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iá)([iaeouü]*)", "a\12", 0)
901 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ié)([iaeouü]*)", "e\12", 0)
902 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iú)([iaeouü]*)", "u\12", 0)
903 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ií)([iaeouü]*)", "i\12", 0)
904 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ió)([iaeouü]*)", "o\12", 0)
905 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǘ)([iaeouü]*)", "v\12", 0)
908 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǎ)([iaeouü]*)", "a\13", 0)
909 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iě)([iaeouü]*)", "e\13", 0)
910 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǔ)([iaeouü]*)", "u\13", 0)
911 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǐ)([iaeouü]*)", "i\13", 0)
912 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǒ)([iaeouü]*)", "o\13", 0)
913 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǚ)([iaeouü]*)", "v\13", 0)
916 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ià)([iaeouü]*)", "a\14", 0)
917 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iè)([iaeouü]*)", "e\14", 0)
918 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iù)([iaeouü]*)", "u\14", 0)
919 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iì)([iaeouü]*)", "i\14", 0)
920 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iò)([iaeouü]*)", "o\14", 0)
921 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǜ)([iaeouü]*)", "v\14", 0)
925 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iå)([iaeouü]*)", "a\10", 0)
926 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e̊([iaeouü]*)", "e\10", 0)
927 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iů)([iaeouü]*)", "u\10", 0)
928 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i̊([iaeouü]*)", "i\10", 0)
929 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o̊([iaeouü]*)", "o\10", 0)
930 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ü̊([iaeouü]*)", "v\10", 0)
932 # Syllables without a tone symbol are tone 0
933 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov]+)([^0-9aeuiov]|\W|$)", "\10\2", 0)
935 # Move numbers to the end of the syllable.
936 # Syllables ending in n and start with g. Note that a syllable cannot start with an u or i
937 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(n)(g[aeuiov])", "\1\3\2\4", 0)
938 # Syllables ending in (ng?) followed by something that is not a valid vowel
939 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(ng?)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
940 # Syllables ending in r
941 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(r)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
943 #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "[\\'\\`]", "", 0)
945 .numberstext$ = .intermediatePinyin$
948 procedure readDisplayPinyin .currentWord
949 select Table 'wordlist$'
950 .pinyin$ = Get value... '.currentWord' Pinyin
951 # Everything to lowercase
953 if index_regex(.pinyin$, "[0-9]") <= 0
954 call pinyin2numbers '.pinyin$'
955 .pinyin$ = pinyin2numbers.numberstext$
959 procedure readPinyin .currentWord
960 call readDisplayPinyin '.currentWord'
961 .pinyin$ = replace_regex$(readDisplayPinyin.pinyin$, ".+", "\L&", 0)
962 .pinyin$ = replace_regex$(.pinyin$, "[\\'\\` ]", "", 0)
966 include ToneProt/SGC_ToneProt.praat
967 include ToneProt/DrawToneContour.praat
968 include ToneProt/HumToneContour.praat
969 include ToneProt/ToneRecognition.praat
970 include ToneProt/ToneScript.praat
971 include ToneProt/ToneRules.praat