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 \bu\bu\bu
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 sgc.currentWordlist
255 .tmpOriginalWordlist = Copy: "Original_'wordlist$'"
257 # Remove current list from All wordlists table
258 select sgc.allWordLists
259 .rowNum = Search column: "Name", wordlistName$
261 .numRows = Get number of rows
265 Set string value: 1, "Name", "---"
270 select sgc.currentWordlist
271 sgc.numberOfWords = Get number of rows
272 .currentWord = sgc.currentWord
273 if .currentWord <= 0 or .currentWord > sgc.numberOfWords or config.shuffleLists
278 call get_feedback_text 'config.language$' AddWordlist
279 call convert_praat_to_latin1 'get_feedback_text.text$'
280 .wordlistText$ = convert_praat_to_latin1.text$
281 call get_feedback_text 'config.language$' Part
282 call convert_praat_to_latin1 'get_feedback_text.text$'
283 .partText$ = convert_praat_to_latin1.text$
284 call get_feedback_text 'config.language$' Tones
285 call convert_praat_to_latin1 'get_feedback_text.text$'
286 .toneText$ = convert_praat_to_latin1.text$
287 call get_feedback_text 'config.language$' Cancel
288 call convert_praat_to_latin1 'get_feedback_text.text$'
289 .cancelText$ = convert_praat_to_latin1.text$
290 call get_feedback_text 'config.language$' Clear
291 call convert_praat_to_latin1 'get_feedback_text.text$'
292 .clearText$ = convert_praat_to_latin1.text$
293 call get_feedback_text 'config.language$' All
294 call convert_praat_to_latin1 'get_feedback_text.text$'
295 .allText$ = convert_praat_to_latin1.text$
296 call get_feedback_text 'config.language$' Previous
297 call convert_praat_to_latin1 'get_feedback_text.text$'
298 .prevWord$ = convert_praat_to_latin1.text$
299 call get_feedback_text 'config.language$' Next
300 call convert_praat_to_latin1 'get_feedback_text.text$'
301 .nextWord$ = convert_praat_to_latin1.text$
302 call get_feedback_text 'config.language$' Continue
303 call convert_praat_to_latin1 'get_feedback_text.text$'
304 .continueText$ = convert_praat_to_latin1.text$
305 call get_feedback_text 'config.language$' Show
306 call convert_praat_to_latin1 'get_feedback_text.text$'
307 .showText$ = convert_praat_to_latin1.text$
309 .pinyinText$ = "Pinyin"
310 .characterText$ = "Character"
313 select sgc.currentWordlist
314 .lessonCol = Get column index: "Lesson"
316 Append column: "Lesson"
317 .lessonCol = Get column index: "Lesson"
318 .numRows = Get number of rows
320 Set string value: .w, "Lesson", "-"
325 # All shown keeps track whether all words are shown
326 # If so, selecting a lesson is preceded by a Clear All
328 # Sort words for consistent selection interface
329 if config.shuffleLists
330 # Allow subdivision in lessons
332 Sort rows... Lesson Pinyin
338 for .i to sgc.numberOfWords
339 .currentLesson$ = Get value: .i, "Lesson"
340 if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index_regex(.lessonList$, "\t'.currentLesson$'\t") <= 0
341 .lessonList$ = .lessonList$ + .currentLesson$ + tab$
343 .lessonName$['.numLessons'] = .currentLesson$
345 .shown$ = Get value: .i, "Show"
353 .numWordsPerScreen = 15
354 while clicked <> 6 and clicked <> 1
359 select sgc.currentWordlist
360 .lessonCol = Get column index: "Lesson"
361 # Sort words for consistent selection interface
362 if config.shuffleLists
363 # Allow subdivision in lessons
365 Sort rows... Lesson Pinyin
370 .max = .numWordsPerScreen - 1
371 if .currentWord + .max > sgc.numberOfWords
372 .max = sgc.numberOfWords - .currentWord
374 for .i from 0 to .numWordsPerScreen - 1
376 .currentPinyin$ = Get value: .currentWord+.i, "Pinyin"
377 if index_regex(.currentPinyin$, "[0-9]") <= 0
378 call pinyin2numbers '.currentPinyin$'
379 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
380 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
382 .pinyin$[.i] = .currentPinyin$
384 .character$[.i] = Get value: .currentWord+.i, "Character"
387 .lessonNum$[.i] = Get value: .currentWord+.i, "Lesson"
388 .lessonNum$[.i] = " : " + .lessonNum$[.i]
390 .showText$[.i] = .pinyin$['.i']
391 if .character$['.i'] <> "-"
392 .showText$[.i] = .pinyin$['.i']+" ("+.character$['.i']+.lessonNum$['.i']+")"
393 elsif .lessonNum$['.i'] <> ""
394 .showText$[.i] = .pinyin$['.i']+" ( -"+.lessonNum$['.i']+")"
396 .showValueText$[.i] = Get value: .currentWord+.i, "Show"
397 if .showValueText$[.i] = "-"
402 .showVariable$[.i] = .pinyin$[.i]
403 .tmp$ = .showVariable$[.i]
404 '.tmp$' = .showValue[.i]
411 # The user text input window (beginPause .... endPause)
412 beginPause(.helpText$)
413 if sgc.allWordLists > 0
414 select sgc.allWordLists
415 .numWordlists = Get number of rows
417 optionMenu: .wordlistText$, 1
419 for .w to .numWordlists
420 select sgc.allWordLists
421 .wordListName$ = Get value: .w, "Name"
422 option: .wordListName$
427 boolean (.showText$[0], .showValue[0])
428 boolean (.showText$[1], .showValue[1])
429 boolean (.showText$[2], .showValue[2])
430 boolean (.showText$[3], .showValue[3])
431 boolean (.showText$[4], .showValue[4])
432 boolean (.showText$[5], .showValue[5])
433 boolean (.showText$[6], .showValue[6])
434 boolean (.showText$[7], .showValue[7])
435 boolean (.showText$[8], .showValue[8])
436 boolean (.showText$[9], .showValue[9])
437 boolean (.showText$[10], .showValue[10])
438 boolean (.showText$[11], .showValue[11])
439 boolean (.showText$[12], .showValue[12])
440 boolean (.showText$[13], .showValue[13])
441 boolean (.showText$[14], .showValue[14])
443 optionMenu: .partText$, 1
446 for .j to .numLessons
447 option: .lessonName$['.j']
450 optionMenu: .toneText$, 1
457 clicked = endPause ("'.cancelText$'", "'.clearText$'", "'.allText$'", "'.prevWord$'", "'.nextWord$'", "'.continueText$'", 6, 1)
459 select sgc.currentWordlist
461 for .i to sgc.numberOfWords
462 Set string value: .i, "Show", "-"
466 for .i to sgc.numberOfWords
467 Set string value: .i, "Show", "+"
471 # Handle added word lists
472 .wordlistText$ = replace_regex$(.wordlistText$, "^(.)", "\l\1", 0)
473 .wordlistText$ = replace_regex$(.wordlistText$, "\s", "_", 0)
474 .tmp$ = '.wordlistText$'$
475 if .tmp$ <> "---" and sgc.allWordLists > 0
476 select sgc.currentWordlist
477 # Add current wordlist name as a lesson name
478 .originalWordList = -1
479 .numRows = Get number of rows
481 select sgc.currentWordlist
482 .currentLesson$ = Get value: .w, "Lesson"
483 if .currentLesson$ = "" or .currentLesson$ = "-"
484 Set string value: .w, "Lesson", wordlist$
488 # Get and merge the selected list
489 select sgc.allWordLists
490 .wordlistNum = Search column: "Name", .tmp$
491 .wordlistPath$ = Get value: .wordlistNum, "Directory"
492 .wordlistPath$ = replace_regex$(.wordlistPath$, "[ ]", "&", 0)
493 call read_wordlist "'.tmp$'" '.wordlistPath$'
494 .newList = read_wordlist.wordlistID
495 call merge_into_wordlist '.newList' '.tmp$'
498 # Add wordlistname to Lesson column
499 select sgc.allWordLists
500 .numRows = Get number of rows
502 Remove row: .wordlistNum
504 Set string value: 1, "Name", "---"
506 # Gather Lesson names
507 select sgc.currentWordlist
508 Sort rows... Lesson Pinyin
510 sgc.numberOfWords = Get number of rows
514 for .i to sgc.numberOfWords
515 .currentLesson$ = Get value: .i, "Lesson"
516 .matchLesson$ = tab$+.currentLesson$+tab$
517 if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
518 .lessonList$ = .lessonList$ + .currentLesson$ + tab$
520 .lessonName$['.numLessons'] = .currentLesson$
522 .shown$ = Get value: .i, "Show"
529 select sgc.currentWordlist
530 # Get selected Part BEFORE we do anything else
532 .tmp$ = replace_regex$(.partText$, "^(.)", "\l\1", 0)
533 .lessonSelected = '.tmp$' - 1
535 if .lessonSelected > 0
538 select sgc.currentWordlist
539 for .i to sgc.numberOfWords
540 # Keep track of whether all are shown
541 .shown$ = Get value: .i, "Show"
546 for .i to sgc.numberOfWords
548 .currentLesson$ = Get value: .i, "Lesson"
549 if .currentLesson$ = .lessonName$['.lessonSelected']
550 Set string value: .i, "Show", "+"
552 Set string value: .i, "Show", "-"
555 for .i to sgc.numberOfWords
556 # Keep track of whether all are shown
557 .shown$ = Get value: .i, "Show"
558 if .firstShown <=0 and .shown$ <> "-"
563 for .i from 0 to .max
564 .tmp$ = replace_regex$(.showVariable$['.i'], "^(.*)$", "\l\1", 0)
565 .showValue['.i'] = '.tmp$'
566 .showWord$['.i'] = "-"
567 if .showValue['.i'] <> 0
568 .showWord$['.i'] = "+"
570 Set string value: .currentWord+.i, "Show", .showWord$['.i']
575 select sgc.currentWordlist
576 .tmp$ = replace_regex$(.toneText$, "^(.)", "\l\1", 0)
577 .toneSelected = '.tmp$' - 2
578 if .toneSelected >= 0
579 select sgc.currentWordlist
580 for .i to sgc.numberOfWords
581 .currentPinyin$ = Get value: .i, "Pinyin"
582 if index_regex(.currentPinyin$, "[0-9]") <= 0
583 call pinyin2numbers '.currentPinyin$'
584 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
585 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
587 .tmp$ = Get value: .i, "Show"
588 if .tmp$ <> "-" and index(.currentPinyin$, "'.toneSelected'") > 0
589 Set string value: .i, "Show", "+"
591 Set string value: .i, "Show", "-"
599 .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
600 elsif .toneSelected < 0
601 .currentWord -= .numWordsPerScreen
604 .currentWord = (sgc.numberOfWords div .numWordsPerScreen) * .numWordsPerScreen + 1
608 .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
609 elsif .toneSelected < 0
610 .currentWord += .numWordsPerScreen
612 if .currentWord > sgc.numberOfWords
617 # Reset and go to the first selected word (can shuffle list)
627 select sgc.currentWordlist
629 select .tmpOriginalWordlist
632 select .tmpOriginalWordlist
634 call Draw_button '.table$' '.label$' 0
637 ###############################################################
639 # Obligatory button Processing Routines
641 # These MUST be defined
643 ###############################################################
645 procedure processMainPageQuit .clickX .clickY .pressed$
649 procedure processMainPageRefresh .clickX .clickY .pressed$
654 procedure processMainPageConfig .clickX .clickY .pressed$
658 procedure processMainPageHelp .clickX .clickY .pressed$
659 call help_loop 'buttons$' init_window
662 procedure processMainPagePlay .clickX .clickY .pressed$
665 if recordedSound$ <> ""
666 call play_sound 'sgc.recordedSound'
669 te.buttonPressValue = mainPage.play
672 procedure Set_Play_Button
674 if recordedSound$ <> ""
677 call Draw_button MainPage Play 'mainPage.play'
680 procedure processMainPageRecord .clickX .clickY .pressed$
682 .recordingTime = recordingTime
683 if count_syllables.number > 2
684 .recordingTime = recordingTime + 1.0*ceiling((count_syllables.number - 2)/2)
686 call record_sound '.recordingTime'
692 call wipeArea 'wipeContourArea$'
694 call draw_tone_contour
696 call display_word_list_name
697 call display_text Black
698 call add_feedback_to_toneevaluation Feedback
699 call write_feedback Feedback
700 select Table Feedback
703 # Do not exercise words that are going well (autoSelect)
704 if add_feedback_to_toneevaluation.result > 0
705 if config.adaptiveLists > 0 and sgc.failedAttempts < 2
706 # Deselect current word
707 select sgc.currentWordlist
708 .i = Search column: "Pinyin", sgc.pinyin$
710 Set string value: .i, "Show", "-"
713 sgc.failedAttempts = 0
715 sgc.failedAttempts += 1
720 ###############################################################
722 # Miscelaneous supporting code
724 ###############################################################
727 procedure generate_example
728 select sgc.currentWordlist
729 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
730 select sgc.currentWordlist
731 .sound$ = Get value... 'sgc.currentWord' Sound
732 call readPinyin 'sgc.currentWord'
733 sgc.pinyin$ = readPinyin.pinyin$
734 if .sound$ = "-" or .sound$ = ""
735 .sound$ = sgc.pinyin$+".wav"
737 if index_regex(.sound$, "^(/|~/|[A-Z]:\\)") > 0
738 .soundFilePath$ = .sound$
740 .soundFilePath$ = localWordlistDir$+"/"+wordlistName$+"/"+.sound$
741 .wordlistDirectory$ = ""
742 if localWordlistDir$ <> "" and fileReadable("'localWordlistDir$'/'wordlistName$'")
743 .wordlistDirectory$ = "'localWordlistDir$'/'wordlistName$'"
744 elsif sgc2wordlists$ <> "" and fileReadable("'sgc2wordlists$'/'wordlistName$'")
745 .wordlistDirectory$ = "'sgc2wordlists$'/'wordlistName$'"
746 elsif globalwordlists$ <> "" and fileReadable("'globalwordlists$'/'wordlistName$'")
747 .wordlistDirectory$ = "'globalwordlists$'/'wordlistName$'"
749 if .wordlistDirectory$ <> ""
750 .audioExampleList = Create Strings as file list... AudioList '.wordlistDirectory$'/'sgc.pinyin$'.*
751 .number_of_examples = Get number of strings
752 if .number_of_examples > 0
754 .sound$ = Get string... 1
755 .soundFilePath$ = "'.wordlistDirectory$'/'.sound$'"
760 if fileReadable(.soundFilePath$) and config.useSoundExample
762 .tmp = nocheck Read from file... '.soundFilePath$'
763 if .tmp != undefined and .tmp > 0
764 call play_sound '.tmp'
768 elsif config.synthesis$ <> "" and config.synthesis$ <> "_DISABLED_"
769 call synthesize_sound 'sgc.pinyin$'
771 call humToneContour 'sgc.pinyin$' 'config.register'
778 # Draw a tone contour
779 procedure draw_tone_contour
780 select sgc.currentWordlist
781 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
782 .sound$ = Get value... 'sgc.currentWord' Sound
783 call readPinyin 'sgc.currentWord'
784 sgc.pinyin$ = readPinyin.pinyin$
785 call drawToneContour 'sgc.pinyin$' 'config.register'
788 if te.recordedPitch > 0
789 call drawSourceToneContour te.recordedPitch
795 procedure recognizeTone
796 select sgc.currentWordlist
797 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
799 if index_regex(config.strict$, "[^0-9]") <= 0
800 .strict = ('config.strict$' >= sgc.highestLevel)
803 .sound$ = Get value... 'sgc.currentWord' Sound
804 call readPinyin 'sgc.currentWord'
805 sgc.pinyin$ = readPinyin.pinyin$
806 call align_recordedSound 'sgc.pinyin$'
807 call sgc_ToneProt 'recordedSound$' 'sgc.pinyin$' 'config.register' '.strict' 'config.language$'
808 # sgc_ToneProt manipulates the sound given. Reconnect
809 select Sound 'recordedSound$'
810 sgc.recordedSound = selected("Sound")
815 procedure write_feedback .table$
816 select Table '.table$'
817 .line1$ = Get value... 1 Text
818 .line2$ = Get value... 2 Text
819 .label$ = Get value... 3 Text
821 # convert numbers to Pinyin if needed
822 if not config.displayNumbers
823 call numbers2pinyin '.line1$'
824 .line1$ = numbers2pinyin.pinyin$
828 if index(.line1$, "???") > 0
830 elsif .label$ = "Correct"
832 elsif config.strict$ = "'sgc.highestLevel'"
833 .line2$ = .line2$ + " *"
836 .currentFeedbackFontSize = 14
838 call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
839 .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
841 call wipeArea 'wipeFeedbackArea$'
842 call set_font_size '.currentFeedbackFontSize'
844 demo Text... 50 Centre 21 Bottom '.line1$'
845 demo Text... 50 Centre 17 Bottom '.line2$'
848 call set_font_size 'defaultFontSize'
852 procedure display_text .color$
853 select sgc.currentWordlist
854 if sgc.currentWord < 0 or sgc.currentWord > sgc.numberOfWords+1
856 if config.shuffleLists
859 if sgc.currentWord < 0
860 sgc.currentWord = sgc.numberOfWords
867 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
869 call readDisplayPinyin 'sgc.currentWord'
870 .displayPinyin$ = readDisplayPinyin.pinyin$
871 .displayChar$ = Get value... 'sgc.currentWord' Character
872 .displayTrans$ = Get value... 'sgc.currentWord' Translation
873 if .displayPinyin$ <> "-" and (config.displayPinyin or sgc.writeAll)
874 if not config.displayNumbers
875 call numbers2pinyin '.displayPinyin$'
876 .displayPinyin$ = numbers2pinyin.pinyin$
879 .displayPinyin$ = replace_regex$(.displayPinyin$, "v", "\\u\X22", 0)
880 .displayText$ = .displayText$ + .displayPinyin$
882 if .displayChar$ <> "-" and (config.displayChar or sgc.writeAll)
883 .displayText$ = .displayText$ + " "+ .displayChar$
886 if .displayTrans$ <> "-" and (config.displayTrans or sgc.writeAll)
887 .displayText$ = .displayText$ + " \s{%%"+ .displayTrans$ + "%}"
889 elsif sgc.currentWord = 0 or sgc.currentWord = sgc.numberOfWords+1
891 .displayText$ = "---"
895 call adjustFontSizeOnHeight 'defaultFont$' 24 15
896 .currentFontSize = adjustFontSizeOnHeight.newFontSize
897 call adjustFontSizeOnWidth 'defaultFont$' '.currentFontSize' 95 '.displayText$'
898 .currentFontSize = adjustFontSizeOnWidth.newFontSize
900 # Clear the writing area
901 call wipeArea 'wipePinyinArea$'
902 # Switch back to Chinese style CJK when in Japanese language mode
903 if .changeCJKstyle and config.language$ = "JA"
904 CJK font style preferences: "Chinese"
906 # Actually display text
908 call set_font_size '.currentFontSize'
909 demo Text... 50 Centre 26 Bottom '.displayText$'
913 call set_font_size 'defaultFontSize'
914 if .changeCJKstyle and config.language$ = "JA"
915 if config.language$ = "JA"
916 CJK font style preferences: "Japanese"
917 elsif config.language$ = "ZH"
918 CJK font style preferences: "Chinese"
921 # Switch back to Japanese style CJK when in Japanese language mode
922 if .changeCJKstyle and config.language$ = "JA"
923 CJK font style preferences: "Japanese"
927 procedure numbers2pinyin .numberstext$
928 .intermediatePinyin$ = .numberstext$
929 # Add a `-quote between vowels
930 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])([aeuiov])", "\1\2'\3", 0)
931 # Move numbers to the nucleus vowel
933 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([^aeuiov0-9]*)([0-9])", "\1\3\2", 0)
935 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([ae])([aeuiov]*)([0-9])", "\1\3\2", 0)
937 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(ou)([0-9])", "o\2u", 0)
938 # or the second vowel
939 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([uiov][aeuiov])([uiov])([0-9])", "\1\3\2", 0)
941 # Convert all tones to special characters
943 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a1", "ā", 0)
944 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e1", "ē", 0)
945 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u1", "ū", 0)
946 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i1", "ī", 0)
947 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o1", "ō", 0)
948 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v1", "ǖ", 0)
949 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "1", "\\-^", 0)
952 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v2", "ǘ", 0)
953 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])2", "\\\1'", 0)
954 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "2", "\\'^", 0)
957 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a3", "ǎ", 0)
958 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e3", "ě", 0)
959 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u3", "ǔ", 0)
960 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i3", "ǐ", 0)
961 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o3", "ǒ", 0)
962 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v3", "ǚ", 0)
963 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "3", "\\N^", 0)
966 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v4", "ǜ", 0)
967 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])4", "\\\1`", 0)
968 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "4", "\\`^", 0)
971 # Remove tone 0 symbol completely
972 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "", 0)
973 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a0", "å", 0)
974 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e0", "e̊", 0)
975 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u0", "ů", 0)
976 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i0", "i̊", 0)
977 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o0", "o̊", 0)
978 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v0", "ü̊", 0)
979 #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "\\0^", 0)
981 # Pick best vowel symbols available in cases not caught before
982 # Ugly clutch to get the 1, 3, 0 tone diacritics at least in the neighbourhood
983 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i(\\[-N0]\^)", "i\\s{_ }\1", 0)
985 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v", "\\u\X22", 0)
987 .pinyin$ = .intermediatePinyin$
990 # NEEDS WORK AND TESTING!!
991 # Convert unicode Pinyin into tone numbers
992 procedure pinyin2numbers .pinyin$
993 .intermediatePinyin$ = .pinyin$
994 # Convert all special characters to numbers
996 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iā)([iaeouü]*)", "a\11", 0)
997 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iē)([iaeouü]*)", "e\11", 0)
998 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iū)([iaeouü]*)", "u\11", 0)
999 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iī)([iaeouü]*)", "i\11", 0)
1000 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iō)([iaeouü]*)", "o\11", 0)
1001 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǖ)([iaeouü]*)", "v\11", 0)
1004 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iá)([iaeouü]*)", "a\12", 0)
1005 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ié)([iaeouü]*)", "e\12", 0)
1006 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iú)([iaeouü]*)", "u\12", 0)
1007 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ií)([iaeouü]*)", "i\12", 0)
1008 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ió)([iaeouü]*)", "o\12", 0)
1009 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǘ)([iaeouü]*)", "v\12", 0)
1012 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǎ)([iaeouü]*)", "a\13", 0)
1013 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iě)([iaeouü]*)", "e\13", 0)
1014 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǔ)([iaeouü]*)", "u\13", 0)
1015 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǐ)([iaeouü]*)", "i\13", 0)
1016 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǒ)([iaeouü]*)", "o\13", 0)
1017 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǚ)([iaeouü]*)", "v\13", 0)
1020 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ià)([iaeouü]*)", "a\14", 0)
1021 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iè)([iaeouü]*)", "e\14", 0)
1022 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iù)([iaeouü]*)", "u\14", 0)
1023 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iì)([iaeouü]*)", "i\14", 0)
1024 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iò)([iaeouü]*)", "o\14", 0)
1025 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǜ)([iaeouü]*)", "v\14", 0)
1029 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iå)([iaeouü]*)", "a\10", 0)
1030 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e̊([iaeouü]*)", "e\10", 0)
1031 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iů)([iaeouü]*)", "u\10", 0)
1032 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i̊([iaeouü]*)", "i\10", 0)
1033 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o̊([iaeouü]*)", "o\10", 0)
1034 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ü̊([iaeouü]*)", "v\10", 0)
1036 # Syllables without a tone symbol are tone 0
1037 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov]+)([^0-9aeuiov]|\W|$)", "\10\2", 0)
1039 # Move numbers to the end of the syllable.
1040 # Syllables ending in n and start with g. Note that a syllable cannot start with an u or i
1041 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(n)(g[aeuiov])", "\1\3\2\4", 0)
1042 # Syllables ending in (ng?) followed by something that is not a valid vowel
1043 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(ng?)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1044 # Syllables ending in r
1045 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(r)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1047 #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "[\\'\\`]", "", 0)
1049 .numberstext$ = .intermediatePinyin$
1052 procedure readDisplayPinyin .currentWord
1053 select sgc.currentWordlist
1054 .pinyin$ = Get value... '.currentWord' Pinyin
1055 # Everything to lowercase
1057 if index_regex(.pinyin$, "[0-9]") <= 0
1058 call pinyin2numbers '.pinyin$'
1059 .pinyin$ = pinyin2numbers.numberstext$
1063 procedure readPinyin .currentWord
1064 call readDisplayPinyin '.currentWord'
1065 .pinyin$ = replace_regex$(readDisplayPinyin.pinyin$, ".+", "\L&", 0)
1066 .pinyin$ = replace_regex$(.pinyin$, "[\\'\\` ]", "", 0)
1070 include ToneProt/SGC_ToneProt.praat
1071 include ToneProt/DrawToneContour.praat
1072 include ToneProt/HumToneContour.praat
1073 include ToneProt/ToneRecognition.praat
1074 include ToneProt/ToneScript.praat
1075 include ToneProt/ToneRules.praat