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
40 if sgc.numberOfDisplayedWords > 0
41 .fraction = sgc.currentWordNum/sgc.numberOfDisplayedWords
43 call drawProgressTriangle -1 .x .y .size .fraction '.color$' Green
44 .currentX = drawProgressTriangle.currentX
45 .endX = .currentX - 0.5
48 .displayColor$ = .color$
49 if sgc.currentWordNum >= sgc.numberOfDisplayedWords
50 .displayColor$ = "Green"
52 demo Paint rectangle... '.displayColor$' '.currentX' '.endX' '.lowY' '.highY'
55 procedure DrawNext .color$ .x .y .size
59 if sgc.numberOfDisplayedWords > 0
60 .fraction = sgc.currentWordNum/sgc.numberOfDisplayedWords
62 call drawProgressTriangle 1 .x .y .size .fraction '.color$' Green
63 .currentX = drawProgressTriangle.currentX
64 .endX = .currentX + 0.5
67 .displayColor$ = .color$
68 if sgc.currentWordNum >= sgc.numberOfDisplayedWords
69 .displayColor$ = "Green"
71 demo Paint rectangle... '.displayColor$' '.currentX' '.endX' '.lowY' '.highY'
74 procedure DrawSelectWords .color$ .x .y .size
78 call adjustFontSizeOnHeight 'defaultFont$' '.currentFontSize' '.maxHeight'
79 .currentFontSize = adjustFontSizeOnHeight.currentFontSize
80 call set_font_size '.currentFontSize'
81 demo Colour... '.color$'
82 demo Text... '.x' Centre '.y' Bottom \bu\bu\bu
83 call set_font_size 'defaultFontSize'
86 procedure DrawWordListUp .color$ .x .y .size
95 demo Draw line... .xleft .ylow .xmidleft .yhigh
96 demo Draw line... .xright .ylow .xmidright .yhigh
97 demo Line width... 'defaultLineWidth'
101 procedure DrawWordListDown .color$ .x .y .size
105 .xmidright = .x - 0.1
110 demo Draw line... .xleft .yhigh .xmidleft .ylow
111 demo Draw line... .xright .yhigh .xmidright .ylow
112 demo Line width... 'defaultLineWidth'
116 procedure drawTriangle .direction .x .y .size
117 # Make sure direction = +/- 1
121 .direction /= abs(.direction)
124 .currentHeight = .size
125 .currentX = .x - .direction*.size
127 demo Line width... 2.0
129 while .currentHeight> 0
130 .ystart = .y + .currentHeight
131 .yend = .y - .currentHeight
132 demo Draw line... .currentX .ystart .currentX .yend
133 .currentHeight -= .offset *3/4
134 .currentX += .direction*.offset * 1.5
136 demo Line width... 'defaultLineWidth'
139 procedure drawProgressTriangle .direction .x .y .size .fraction .color1$ .color2$
140 # Make sure direction = +/- 1
144 .direction /= abs(.direction)
147 .currentHeight = .size
148 .startX = .x - .direction*.size
151 demo Line width... 2.0
153 while .currentHeight> 0
154 # Implement progress bar in .color2$
155 if .direction*(.currentX - .startX)/.size <= 2*.fraction
161 .ystart = .y + .currentHeight
162 .yend = .y - .currentHeight
163 demo Draw line... .currentX .ystart .currentX .yend
164 .currentHeight -= .offset *3/4
165 .currentX += .direction*.offset * 1.5
167 demo Line width... 'defaultLineWidth'
171 ###############################################################
173 # Obligatory button Drawing Routines
175 # These MUST be defined
177 ###############################################################
179 procedure DrawRecord .color$ .x .y .size
181 demo Paint circle... '.color$' '.x' '.y' '.size'
184 procedure DrawPlay .color$ .x .y .size
186 call drawTriangle 1 .x .y .size
189 procedure DrawQuit .color$ .x .y .size
190 demo Colour... '.color$'
191 .lineWidth = 0.5*.size**2
192 demo Line width... '.lineWidth'
197 demo Draw line... .xstart .ystart .xend .yend
202 demo Draw line... .xstart .ystart .xend .yend
203 demo Line width... 'defaultLineWidth'
207 procedure DrawConfig .color$ .x .y .size
209 .lineWidth = 0.4*.size
210 demo Arrow size... '.lineWidth'
211 .lineWidth = 0.4*.size**2
212 demo Line width... '.lineWidth'
216 demo Draw arrow... .xstart .y .xend .y
217 demo Line width... 'defaultLineWidth'
220 procedure DrawRefresh .color$ .x .y .size
221 .lineWidth = 0.5*.size**2
223 demo Line width... '.lineWidth'
224 demo Draw arc... '.x' '.y' '.size' 0 270
225 demo Line width... 'defaultLineWidth'
228 ###############################################################
230 # Button Processing Routines
232 ###############################################################
234 procedure processMainPageExample .clickX .clickY .pressed$
235 call generate_example
238 procedure processMainPagePrevious .clickX .clickY .pressed$
240 call display_text Grey
243 call wipeArea 'wipeFeedbackArea$'
245 call display_text Black
247 sgc.failedAttempts = 0
250 procedure processMainPageNext .clickX .clickY .pressed$
252 call display_text Grey
254 call wipeArea 'wipeFeedbackArea$'
257 call display_text Black
260 procedure processMainPageWordlistUp .clickX .clickY .pressed$
261 call wipeArea 'wipeFeedbackArea$'
262 call load_word_list "'localWordlistDir$'" -1
264 call display_text Black
267 procedure processMainPageWordlistDown .clickX .clickY .pressed$
268 call wipeArea 'wipeFeedbackArea$'
269 call load_word_list "'localWordlistDir$'" 1
271 call display_text Black
274 procedure processMainPageGRADE .clickX .clickY .pressed$
275 call setGrade '.pressed$'
280 procedure processMainPagePinYinArea .clickX .clickY .pressed$
283 call display_text Red
287 # Select the words to practise. This is quite a complex piece of code
288 procedure processMainPageSelectWords .clickX .clickY .pressed$
290 .label$ = "SelectWords"
291 call Draw_button '.table$' '.label$' 1
294 call findLabel '.table$' '.label$'
296 select Table '.table$'
297 .helpText$ = Get value... '.row' Helptext
298 call convert_praat_to_latin1 '.helpText$'
299 .helpText$ = convert_praat_to_latin1.text$
302 select sgc.currentWordlist
303 .tmpOriginalWordlist = Copy: "Original_'wordlist$'"
305 # Remove current list from All wordlists table
306 select sgc.allWordLists
307 .rowNum = Search column: "Name", wordlistName$
309 .numRows = Get number of rows
313 Set string value: 1, "Name", "---"
318 select sgc.currentWordlist
319 sgc.numberOfWords = Get number of rows
320 .currentWord = sgc.currentWord
321 if .currentWord <= 0 or .currentWord > sgc.numberOfWords or config.shuffleLists
326 call get_feedback_text 'config.language$' SelectWordlist
327 call convert_praat_to_latin1 'get_feedback_text.text$'
328 .selectWordlistText$ = convert_praat_to_latin1.text$
329 call get_feedback_text 'config.language$' AddWordlist
330 call convert_praat_to_latin1 'get_feedback_text.text$'
331 .wordlistText$ = convert_praat_to_latin1.text$
332 call get_feedback_text 'config.language$' Part
333 call convert_praat_to_latin1 'get_feedback_text.text$'
334 .partText$ = convert_praat_to_latin1.text$
335 call get_feedback_text 'config.language$' Tones
336 call convert_praat_to_latin1 'get_feedback_text.text$'
337 .toneText$ = convert_praat_to_latin1.text$
338 call get_feedback_text 'config.language$' Cancel
339 call convert_praat_to_latin1 'get_feedback_text.text$'
340 .cancelText$ = convert_praat_to_latin1.text$
341 call get_feedback_text 'config.language$' Clear
342 call convert_praat_to_latin1 'get_feedback_text.text$'
343 .clearText$ = convert_praat_to_latin1.text$
344 call get_feedback_text 'config.language$' All
345 call convert_praat_to_latin1 'get_feedback_text.text$'
346 .allText$ = convert_praat_to_latin1.text$
347 call get_feedback_text 'config.language$' Apply
348 call convert_praat_to_latin1 'get_feedback_text.text$'
349 .applySelection$ = convert_praat_to_latin1.text$
350 call get_feedback_text 'config.language$' Next
351 call convert_praat_to_latin1 'get_feedback_text.text$'
352 .nextWord$ = convert_praat_to_latin1.text$
353 call get_feedback_text 'config.language$' Continue
354 call convert_praat_to_latin1 'get_feedback_text.text$'
355 .continueText$ = convert_praat_to_latin1.text$
356 call get_feedback_text 'config.language$' Show
357 call convert_praat_to_latin1 'get_feedback_text.text$'
358 .showText$ = convert_praat_to_latin1.text$
360 call get_evaluation_text 'config.language$' Pinyin
361 .pinyinText$ = get_evaluation_text.text$
363 call get_evaluation_text 'config.language$' Character
364 .characterText$ = get_evaluation_text.text$
366 call get_evaluation_text 'config.language$' Example
367 .exampleText$ = get_evaluation_text.text$
369 call get_evaluation_text 'config.language$' Translation
370 .translationText$ = get_evaluation_text.text$
372 call get_evaluation_text 'config.language$' ManualEntry
373 .manualEntryText$ = get_evaluation_text.text$
376 select sgc.currentWordlist
377 .lessonCol = Get column index: "Lesson"
379 Append column: "Lesson"
380 .lessonCol = Get column index: "Lesson"
381 .numRows = Get number of rows
383 Set string value: .w, "Lesson", "-"
387 # All shown keeps track whether all words are shown
388 # If so, selecting a lesson is preceded by a Clear All
392 .numWordsPerScreen = 15
393 while clicked <> 6 and clicked <> 1
398 # A new list might have been added!
403 select sgc.currentWordlist
404 .lessonCol = Get column index: "Lesson"
406 Append column: "Lesson"
407 .lessonCol = Get column index: "Lesson"
408 .numRows = Get number of rows
410 Set string value: .w, "Lesson", "-"
416 # All shown keeps track whether all words are shown
417 # If so, selecting a lesson is preceded by a Clear All
419 # Sort words for consistent selection interface
420 if config.shuffleLists
421 # Allow subdivision in lessons
423 Sort rows... Lesson Pinyin
429 for .i to sgc.numberOfWords
430 .currentLesson$ = Get value: .i, "Lesson"
431 .matchLesson$ = tab$+.currentLesson$+tab$
432 if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
433 .lessonList$ = .lessonList$ + .currentLesson$ + tab$
435 .lessonName$['.numLessons'] = .currentLesson$
437 .shown$ = Get value: .i, "Show"
445 # Sort words for consistent selection interface (watch out, List can be changed)
446 if config.shuffleLists
447 # Allow subdivision in lessons
449 Sort rows... Lesson Pinyin
454 .max = .numWordsPerScreen - 1
455 if .currentWord + .max > sgc.numberOfWords
456 .max = sgc.numberOfWords - .currentWord
458 for .i from 0 to .numWordsPerScreen - 1
460 .currentPinyin$ = Get value: .currentWord+.i, sgcwordlist.word$
461 if index_regex(.currentPinyin$, "[0-9]") <= 0
462 call pinyin2numbers '.currentPinyin$'
463 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
464 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
466 .pinyin$[.i] = .currentPinyin$
468 .character$[.i] = Get value: .currentWord+.i, sgcwordlist.graph$
471 .lessonNum$[.i] = Get value: .currentWord+.i, "Lesson"
472 .lessonNum$[.i] = " : " + .lessonNum$[.i]
474 .showText$[.i] = .pinyin$['.i']
475 if .character$['.i'] <> "-"
476 .showText$[.i] = .pinyin$['.i']+" ("+.character$['.i']+.lessonNum$['.i']+")"
477 elsif .lessonNum$['.i'] <> ""
478 .showText$[.i] = .pinyin$['.i']+" ( -"+.lessonNum$['.i']+")"
480 .showValueText$[.i] = Get value: .currentWord+.i, "Show"
481 if .showValueText$[.i] = "-"
486 .showVariable$[.i] = .pinyin$[.i]
487 # This prevents some nasty attempts to use language elements as variables
488 if index_regex(.showVariable$[.i], "[^0-9r]$") or index_regex(.showVariable$[.i], "[0-9]") <= 0
489 .showVariable$[.i] = .pinyin$[.i]+"0"
491 .tmp$ = replace_regex$(.showVariable$[.i], "^(.+)$", "\l\1", 0)
492 .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
493 '.tmp$' = .showValue[.i]
500 # The user text input window (beginPause .... endPause)
501 beginPause(.helpText$)
502 if sgc.allWordLists > 0
503 select sgc.allWordLists
504 .numWordlists = Get number of rows
505 optionMenu: .selectWordlistText$, 1
507 for .w to .numWordlists
508 select sgc.allWordLists
509 .wordListName$ = Get value: .w, "Name"
510 option: .wordListName$
516 if sgc.allWordLists > 0
517 select sgc.allWordLists
518 .numWordlists = Get number of rows
519 optionMenu: .wordlistText$, 1
521 for .w to .numWordlists
522 select sgc.allWordLists
523 .wordListName$ = Get value: .w, "Name"
524 option: .wordListName$
526 option: "*"+.manualEntryText$+"*"
529 boolean (.showText$[0], .showValue[0])
530 boolean (.showText$[1], .showValue[1])
531 boolean (.showText$[2], .showValue[2])
532 boolean (.showText$[3], .showValue[3])
533 boolean (.showText$[4], .showValue[4])
534 boolean (.showText$[5], .showValue[5])
535 boolean (.showText$[6], .showValue[6])
536 boolean (.showText$[7], .showValue[7])
537 boolean (.showText$[8], .showValue[8])
538 boolean (.showText$[9], .showValue[9])
539 boolean (.showText$[10], .showValue[10])
540 boolean (.showText$[11], .showValue[11])
541 boolean (.showText$[12], .showValue[12])
542 boolean (.showText$[13], .showValue[13])
543 boolean (.showText$[14], .showValue[14])
545 .selectMenu$ = .toneText$
547 .selectMenu$ = .selectMenu$ + " " + .partText$
549 optionMenu: .selectMenu$, 1
557 # Display Lesson text if available
561 for .j to .numLessons
562 option: .partText$+": "+.lessonName$['.j']
565 clicked = endPause ("'.cancelText$'", "'.clearText$'", "'.allText$'", "'.applySelection$'", "'.nextWord$'", "'.continueText$'", 6, 1)
567 select sgc.currentWordlist
569 for .i to sgc.numberOfWords
570 Set string value: .i, "Show", "-"
574 for .i to sgc.numberOfWords
575 Set string value: .i, "Show", "+"
579 # Switch to new wordlist
580 .tmp$ = replace_regex$(.selectWordlistText$, "^(.)", "\l\1", 0)
581 .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
583 if .tmp$ <> "---" and sgc.allWordLists > 0
585 select sgc.allWordLists
586 .wordlistNum = Search column: "Name", .tmp$
588 wordlistName$ = .tmp$
589 call load_word_list "'localWordlistDir$'" 0
593 goto NEXTSELECTWORDLOOP
598 # Handle added word lists
599 .tmp$ = replace_regex$(.wordlistText$, "^(.)", "\l\1", 0)
600 .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
602 if .tmp$ <> "---" and sgc.allWordLists > 0
603 select sgc.currentWordlist
604 # Add current wordlist name as a lesson name
605 .originalWordList = -1
606 .numRows = Get number of rows
608 select sgc.currentWordlist
609 .currentLesson$ = Get value: .w, "Lesson"
610 if .currentLesson$ = "" or .currentLesson$ = "-"
611 Set string value: .w, "Lesson", wordlist$
615 # Get and merge the selected list
616 # Enter words by hand
617 if .tmp$ = "*"+.manualEntryText$+"*"
619 .currentFilePath$ = .exampleText$
620 .manualText$ = .manualEntryText$
621 .manPinyin$ = .pinyinText$
622 .manCharacter$ = .characterText$
623 .manTranslation$ = .translationText$
624 .manSound$ = .currentFilePath$
625 .manLesson$ = .manualText$
626 while .man_clicked > 1
627 beginPause: .manualEntryText$
628 text: .pinyinText$, .manPinyin$
629 text: .characterText$, .manCharacter$
630 text: .translationText$, .manTranslation$
631 text: .exampleText$, .manSound$
632 text: .manualText$, .manualText$
633 .man_clicked = endPause("'.cancelText$'", "'.exampleText$'", "'.continueText$'", 3, 1)
635 .tmp$ = replace_regex$(.pinyinText$, "\s", "_", 0)
636 .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
637 if '.tmp$'$ <> .pinyinText$
638 .manPinyin$ = '.tmp$'$
644 .tmp$ = replace_regex$(.characterText$, "\s", "_", 0)
645 .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
646 if '.tmp$'$ <> .characterText$
647 .manCharacter$ = '.tmp$'$
652 .tmp$ = replace_regex$(.translationText$, "\s", "_", 0)
653 .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
654 if '.tmp$'$ <> .translationText$
655 .manTranslation$ = '.tmp$'$
657 .manTranslation$ = ""
660 .tmp$ = replace_regex$(.exampleText$, "\s", "_", 0)
661 .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
662 if '.tmp$'$ <> .characterText$ and '.tmp$'$ <> ""
663 .manSound$ = '.tmp$'$
666 .tmp$ = replace_regex$(.manualText$, "\s", "_", 0)
667 .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
668 .manLesson$ = '.tmp$'$
671 .manSound$ = chooseReadFile$(.exampleText$);
672 elsif .man_clicked = 3
673 # Clean up input string
674 .manPinyin$ = replace_regex$(.manPinyin$, "^[^a-z]+", "", 0)
675 .manPinyin$ = replace_regex$(.manPinyin$, "[^a-zA-Z0-9_']", "", 0)
677 select sgc.currentWordlist
679 .numRows = Get number of rows
681 Set string value: .numRows, sgcwordlist.word$, .manPinyin$
682 Set string value: .numRows, sgcwordlist.graph$, .manCharacter$
683 Set string value: .numRows, sgcwordlist.transl$, .manTranslation$
684 Set string value: .numRows, sgcwordlist.audio$, .manSound$
685 Set string value: .numRows, "Lesson", .manLesson$
686 Set string value: .numRows, "Show", "+"
688 .manualText$ = .manualEntryText$
689 .manPinyin$ = .pinyinText$
690 .manCharacter$ = .characterText$
691 .manTranslation$ = .translationText$
692 .manSound$ = .currentFilePath$
693 .manLesson$ = .manualText$
699 select sgc.allWordLists
700 .wordlistNum = Search column: "Name", .tmp$
702 .wordlistPath$ = Get value: .wordlistNum, "Directory"
703 .wordlistPath$ = replace_regex$(.wordlistPath$, "[ ]", "&", 0)
704 call read_wordlist "'.tmp$'" '.wordlistPath$'
705 .newList = read_wordlist.wordlistID
706 call merge_into_wordlist '.newList' '.tmp$'
709 # Add wordlistname to Lesson column
710 select sgc.allWordLists
711 .numRows = Get number of rows
713 Remove row: .wordlistNum
715 Set string value: 1, "Name", "---"
719 # Gather Lesson names
720 select sgc.currentWordlist
721 Sort rows... Lesson Pinyin
723 sgc.numberOfWords = Get number of rows
727 for .i to sgc.numberOfWords
728 .currentLesson$ = Get value: .i, "Lesson"
729 .matchLesson$ = tab$+.currentLesson$+tab$
730 if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
731 .lessonList$ = .lessonList$ + .currentLesson$ + tab$
733 .lessonName$['.numLessons'] = .currentLesson$
735 .shown$ = Get value: .i, "Show"
742 for .i from 0 to .max
743 .tmp$ = replace_regex$(.showVariable$['.i'], "^(.*)$", "\l\1", 0)
744 .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
746 .showValue['.i'] = '.tmp$'
747 .showWord$['.i'] = "-"
748 if .showValue['.i'] <> 0
749 .showWord$['.i'] = "+"
751 Set string value: .currentWord+.i, "Show", .showWord$['.i']
755 select sgc.currentWordlist
756 .tmp$ = replace_regex$(.selectMenu$, "^(.)", "\l\1", 0)
757 .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
758 .toneSelected = '.tmp$' - 2
759 if .toneSelected >= 0 and .toneSelected < 5
760 select sgc.currentWordlist
761 for .i to sgc.numberOfWords
762 .currentPinyin$ = Get value: .i, sgcwordlist.word$
763 if index_regex(.currentPinyin$, "[0-9]") <= 0
764 call pinyin2numbers '.currentPinyin$'
765 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
766 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
768 .tmp$ = Get value: .i, "Show"
769 if .tmp$ <> "-" and index(.currentPinyin$, "'.toneSelected'") > 0
770 Set string value: .i, "Show", "+"
772 Set string value: .i, "Show", "-"
776 elsif .toneSelected > 5
777 # .toneSelected = 5 is the Part text
778 .lessonSelected = .toneSelected - 5
779 if .lessonSelected > 0
782 select sgc.currentWordlist
783 for .i to sgc.numberOfWords
784 # Keep track of whether all are shown
785 .shown$ = Get value: .i, "Show"
791 for .i to sgc.numberOfWords
793 .currentLesson$ = Get value: .i, "Lesson"
794 if .currentLesson$ = .lessonName$['.lessonSelected']
795 Set string value: .i, "Show", "+"
797 Set string value: .i, "Show", "-"
800 for .i to sgc.numberOfWords
801 # Keep track of whether all are shown
802 .shown$ = Get value: .i, "Show"
803 if .firstShown <=0 and .shown$ <> "-"
812 .currentWord = (sgc.numberOfWords div .numWordsPerScreen) * .numWordsPerScreen + 1
816 .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
818 .currentWord += .numWordsPerScreen
819 if .currentWord > sgc.numberOfWords
824 # Reset and go to the first selected word (can shuffle list)
831 label NEXTSELECTWORDLOOP
836 select sgc.currentWordlist
838 select .tmpOriginalWordlist
840 sgc.currentWordlist = selected()
842 # Set the values of the number of words shown
843 select sgc.currentWordlist
844 .numWords = Get number of rows
845 sgc.currentWordNum = 1
846 sgc.numberOfDisplayedWords = 0
849 .show$ = Get value: .i, "Show"
851 if sgc.currentWord < 1
854 sgc.numberOfDisplayedWords += 1
858 select .tmpOriginalWordlist
861 label SELECTWORDSFAIL
863 call Draw_button '.table$' '.label$' 0
866 ###############################################################
868 # Obligatory button Processing Routines
870 # These MUST be defined
872 ###############################################################
874 procedure processMainPageQuit .clickX .clickY .pressed$
878 procedure processMainPageRefresh .clickX .clickY .pressed$
883 procedure processMainPageConfig .clickX .clickY .pressed$
887 procedure processMainPageHelp .clickX .clickY .pressed$
888 call help_loop 'buttons$' init_window
891 procedure processMainPagePlay .clickX .clickY .pressed$
894 if recordedSound$ <> ""
895 call play_sound 'sgc.recordedSound'
898 te.buttonPressValue = mainPage.play
901 procedure Set_Play_Button
903 if recordedSound$ <> ""
906 call Draw_button MainPage Play 'mainPage.play'
909 procedure processMainPageRecord .clickX .clickY .pressed$
911 .recordingTime = recordingTime
912 if count_syllables.number > 2
913 .recordingTime = recordingTime + 1.0*ceiling((count_syllables.number - 2)/2)
915 call record_sound '.recordingTime'
921 call wipeArea 'wipeContourArea$'
923 call draw_tone_contour
925 call display_word_list_name
926 call display_text Black
927 call add_feedback_to_toneevaluation Feedback
928 call write_feedback Feedback
929 select Table Feedback
932 # Do not exercise words that are going well (autoSelect)
933 if add_feedback_to_toneevaluation.result > 0
934 if config.adaptiveLists > 0 and sgc.failedAttempts < 2
935 # Deselect current word
936 select sgc.currentWordlist
937 .i = Search column: sgcwordlist.word$, sgc.pinyin$
939 Set string value: .i, "Show", "-"
942 sgc.failedAttempts = 0
944 sgc.failedAttempts += 1
949 ###############################################################
951 # Miscelaneous supporting code
953 ###############################################################
956 procedure generate_example
957 select sgc.currentWordlist
958 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
959 select sgc.currentWordlist
960 .sound$ = Get value... 'sgc.currentWord' Sound
961 call readPinyin 'sgc.currentWord'
962 sgc.pinyin$ = readPinyin.pinyin$
963 sgc.character$ = readPinyin.character$
964 if .sound$ = "-" or .sound$ = ""
965 .sound$ = sgc.pinyin$+".wav"
967 if index_regex(.sound$, "^(/|~/|[A-Z]:\\)") > 0
968 .soundFilePath$ = .sound$
970 .soundFilePath$ = localWordlistDir$+"/"+wordlistName$+"/"+.sound$
971 .wordlistDirectory$ = ""
972 if localWordlistDir$ <> "" and fileReadable("'localWordlistDir$'/'wordlistName$'")
973 .wordlistDirectory$ = "'localWordlistDir$'/'wordlistName$'"
974 elsif sgc2wordlists$ <> "" and fileReadable("'sgc2wordlists$'/'wordlistName$'")
975 .wordlistDirectory$ = "'sgc2wordlists$'/'wordlistName$'"
976 elsif globalwordlists$ <> "" and fileReadable("'globalwordlists$'/'wordlistName$'")
977 .wordlistDirectory$ = "'globalwordlists$'/'wordlistName$'"
979 if .wordlistDirectory$ <> ""
980 .audioExampleList = Create Strings as file list... AudioList '.wordlistDirectory$'/'sgc.pinyin$'.*
981 .number_of_examples = Get number of strings
982 if .number_of_examples > 0
984 .sound$ = Get string... 1
985 .soundFilePath$ = "'.wordlistDirectory$'/'.sound$'"
990 if fileReadable(.soundFilePath$) and config.useSoundExample
992 .tmp = nocheck Read from file... '.soundFilePath$'
993 if .tmp != undefined and .tmp > 0
994 call play_sound '.tmp'
998 elsif config.synthesis$ <> "" and config.synthesis$ <> "_DISABLED_"
999 call synthesize_sound "'sgc.pinyin$'" "'sgc.character$'"
1001 call humToneContour 'sgc.pinyin$' 'config.register'
1008 # Draw a tone contour
1009 procedure draw_tone_contour
1010 select sgc.currentWordlist
1011 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
1012 .sound$ = Get value... 'sgc.currentWord' Sound
1013 call readPinyin 'sgc.currentWord'
1014 sgc.pinyin$ = readPinyin.pinyin$
1015 sgc.character$ = readPinyin.character$
1016 call drawToneContour 'sgc.pinyin$' 'config.register'
1019 if te.recordedPitch > 0
1020 call drawSourceToneContour te.recordedPitch
1026 procedure recognizeTone
1027 select sgc.currentWordlist
1028 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
1030 if index_regex(config.strict$, "[^0-9]") <= 0
1031 .strict = ('config.strict$' >= sgc.highestLevel)
1034 .sound$ = Get value... 'sgc.currentWord' Sound
1035 call readPinyin 'sgc.currentWord'
1036 sgc.pinyin$ = readPinyin.pinyin$
1037 sgc.character$ = readPinyin.character$
1038 call align_recordedSound 'sgc.pinyin$'
1039 call sgc_ToneProt 'recordedSound$' 'sgc.pinyin$' 'config.register' '.strict' 'config.language$'
1040 # sgc_ToneProt manipulates the sound given. Reconnect
1041 select Sound 'recordedSound$'
1042 sgc.recordedSound = selected(sgcwordlist.audio$)
1047 procedure write_feedback .table$
1048 select Table '.table$'
1049 .line1$ = Get value... 1 Text
1050 .line2$ = Get value... 2 Text
1051 .label$ = Get value... 3 Text
1053 # convert numbers to Pinyin if needed
1054 if not config.displayNumbers
1055 call numbers2pinyin '.line1$'
1056 .line1$ = numbers2pinyin.pinyin$
1060 if index(.line1$, "???") > 0
1062 elsif .label$ = "Correct"
1064 elsif config.strict$ = "'sgc.highestLevel'"
1065 .line2$ = .line2$ + " *"
1068 .currentFeedbackFontSize = 14
1069 .maxHeight = 21 - 17
1070 call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
1071 .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
1073 call wipeArea 'wipeFeedbackArea$'
1074 call set_font_size '.currentFeedbackFontSize'
1076 demo Text... 50 Centre 21 Bottom '.line1$'
1077 demo Text... 50 Centre 17 Bottom '.line2$'
1080 call set_font_size 'defaultFontSize'
1083 procedure write_grade .pinyin$
1084 if sgc2.performanceTable > 0 and .pinyin$ <> ""
1085 select sgc2.performanceTable
1086 call getGrade '.pinyin$'
1087 if getGrade.grade > 0
1088 call get_evaluation_text 'config.language$' 'getGrade.grade'
1089 .currentGrade$ = get_evaluation_text.text$
1090 .line1$ = .currentGrade$
1093 .currentFeedbackFontSize = 40
1094 .maxHeight = 2* (21 - 17 - 1)
1095 call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
1096 .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
1098 call wipeArea 'wipeFeedbackArea$'
1099 call set_font_size '.currentFeedbackFontSize'
1101 demo Text... 50 Centre 17 Bottom '.line1$'
1104 call set_font_size 'defaultFontSize'
1110 procedure display_text .color$
1111 select sgc.currentWordlist
1112 if sgc.currentWord < 0 or sgc.currentWord > sgc.numberOfWords+1
1114 if config.shuffleLists
1117 if sgc.currentWord < 0
1118 sgc.currentWord = sgc.numberOfWords
1125 if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
1127 call readDisplayPinyin 'sgc.currentWord'
1128 .displayPinyin$ = readDisplayPinyin.pinyin$
1129 .displayChar$ = Get value... 'sgc.currentWord' Character
1130 .displayTrans$ = Get value... 'sgc.currentWord' Translation
1131 if .displayPinyin$ <> "-" and (config.displayPinyin or sgc.writeAll)
1132 if not config.displayNumbers
1133 call numbers2pinyin '.displayPinyin$'
1134 .displayPinyin$ = numbers2pinyin.pinyin$
1137 .displayPinyin$ = replace_regex$(.displayPinyin$, "v", "\\u\X22", 0)
1138 .displayText$ = .displayText$ + .displayPinyin$
1140 if .displayChar$ <> "-" and (config.displayChar or sgc.writeAll)
1141 .displayText$ = .displayText$ + " "+ .displayChar$
1144 if .displayTrans$ <> "-" and (config.displayTrans or sgc.writeAll)
1145 .displayText$ = .displayText$ + " \s{%%"+ .displayTrans$ + "%}"
1147 elsif sgc.currentWord = 0 or sgc.currentWord = sgc.numberOfWords+1
1149 .displayText$ = "---"
1153 call adjustFontSizeOnHeight 'defaultFont$' 24 15
1154 .currentFontSize = adjustFontSizeOnHeight.newFontSize
1155 call adjustFontSizeOnWidth 'defaultFont$' '.currentFontSize' 95 '.displayText$'
1156 .currentFontSize = adjustFontSizeOnWidth.newFontSize
1158 # Clear the writing area
1159 call wipeArea 'wipePinyinArea$'
1160 # Switch back to Chinese style CJK when in Japanese language mode
1161 if .changeCJKstyle and config.language$ = "JA"
1162 CJK font style preferences: "Chinese"
1164 # Actually display text
1166 call set_font_size '.currentFontSize'
1167 demo Text... 50 Centre 26 Bottom '.displayText$'
1171 call set_font_size 'defaultFontSize'
1172 if .changeCJKstyle and config.language$ = "JA"
1173 if config.language$ = "JA"
1174 CJK font style preferences: "Japanese"
1175 elsif config.language$ = "ZH"
1176 CJK font style preferences: "Chinese"
1179 # Switch back to Japanese style CJK when in Japanese language mode
1180 if .changeCJKstyle and config.language$ = "JA"
1181 CJK font style preferences: "Japanese"
1185 procedure numbers2pinyin .numberstext$
1186 .intermediatePinyin$ = .numberstext$
1187 # Add a `-quote between vowels
1188 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])([aeuiov])", "\1\2'\3", 0)
1189 # Move numbers to the nucleus vowel
1191 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([^aeuiov0-9]*)([0-9])", "\1\3\2", 0)
1193 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([ae])([aeuiov]*)([0-9])", "\1\3\2", 0)
1195 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(ou)([0-9])", "o\2u", 0)
1196 # or the second vowel
1197 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([uiov][aeuiov])([uiov])([0-9])", "\1\3\2", 0)
1199 # Convert all tones to special characters
1201 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a1", "ā", 0)
1202 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e1", "ē", 0)
1203 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u1", "ū", 0)
1204 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i1", "ī", 0)
1205 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o1", "ō", 0)
1206 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v1", "ǖ", 0)
1207 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "1", "\\-^", 0)
1210 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v2", "ǘ", 0)
1211 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])2", "\\\1'", 0)
1212 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "2", "\\'^", 0)
1215 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a3", "ǎ", 0)
1216 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e3", "ě", 0)
1217 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u3", "ǔ", 0)
1218 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i3", "ǐ", 0)
1219 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o3", "ǒ", 0)
1220 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v3", "ǚ", 0)
1221 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "3", "\\N^", 0)
1224 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v4", "ǜ", 0)
1225 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])4", "\\\1`", 0)
1226 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "4", "\\`^", 0)
1229 # Remove tone 0 symbol completely
1230 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "", 0)
1231 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a0", "å", 0)
1232 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e0", "e̊", 0)
1233 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u0", "ů", 0)
1234 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i0", "i̊", 0)
1235 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o0", "o̊", 0)
1236 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v0", "ü̊", 0)
1237 #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "\\0^", 0)
1239 # Pick best vowel symbols available in cases not caught before
1240 # Ugly clutch to get the 1, 3, 0 tone diacritics at least in the neighbourhood
1241 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i(\\[-N0]\^)", "i\\s{_ }\1", 0)
1243 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v", "\\u\X22", 0)
1245 .pinyin$ = .intermediatePinyin$
1248 # NEEDS WORK AND TESTING!!
1249 # Convert unicode Pinyin into tone numbers
1250 procedure pinyin2numbers .pinyin$
1251 .intermediatePinyin$ = .pinyin$
1252 # Convert all special characters to numbers
1254 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iā)([iaeouü]*)", "a\11", 0)
1255 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iē)([iaeouü]*)", "e\11", 0)
1256 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iū)([iaeouü]*)", "u\11", 0)
1257 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iī)([iaeouü]*)", "i\11", 0)
1258 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iō)([iaeouü]*)", "o\11", 0)
1259 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǖ)([iaeouü]*)", "v\11", 0)
1262 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iá)([iaeouü]*)", "a\12", 0)
1263 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ié)([iaeouü]*)", "e\12", 0)
1264 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iú)([iaeouü]*)", "u\12", 0)
1265 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ií)([iaeouü]*)", "i\12", 0)
1266 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ió)([iaeouü]*)", "o\12", 0)
1267 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǘ)([iaeouü]*)", "v\12", 0)
1270 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǎ)([iaeouü]*)", "a\13", 0)
1271 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iě)([iaeouü]*)", "e\13", 0)
1272 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǔ)([iaeouü]*)", "u\13", 0)
1273 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǐ)([iaeouü]*)", "i\13", 0)
1274 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǒ)([iaeouü]*)", "o\13", 0)
1275 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǚ)([iaeouü]*)", "v\13", 0)
1278 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ià)([iaeouü]*)", "a\14", 0)
1279 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iè)([iaeouü]*)", "e\14", 0)
1280 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iù)([iaeouü]*)", "u\14", 0)
1281 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iì)([iaeouü]*)", "i\14", 0)
1282 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iò)([iaeouü]*)", "o\14", 0)
1283 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǜ)([iaeouü]*)", "v\14", 0)
1287 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iå)([iaeouü]*)", "a\10", 0)
1288 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e̊([iaeouü]*)", "e\10", 0)
1289 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iů)([iaeouü]*)", "u\10", 0)
1290 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i̊([iaeouü]*)", "i\10", 0)
1291 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o̊([iaeouü]*)", "o\10", 0)
1292 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ü̊([iaeouü]*)", "v\10", 0)
1294 # Syllables without a tone symbol are tone 0
1295 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov]+)([^0-9aeuiov]|\W|$)", "\10\2", 0)
1297 # Move numbers to the end of the syllable.
1298 # Syllables ending in n and start with g. Note that a syllable cannot start with an u or i
1299 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(n)(g[aeuiov])", "\1\3\2\4", 0)
1300 # Syllables ending in (ng?) followed by something that is not a valid vowel
1301 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(ng?)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1302 # Syllables ending in r
1303 .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(r)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1305 #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "[\\'\\`]", "", 0)
1307 .numberstext$ = .intermediatePinyin$
1310 procedure readDisplayPinyin .currentWord
1311 select sgc.currentWordlist
1312 .pinyin$ = Get value... '.currentWord' Pinyin
1313 .character$ = Get value... '.currentWord' Character
1314 # Everything to lowercase
1316 if index_regex(.pinyin$, "[0-9]") <= 0
1317 call pinyin2numbers '.pinyin$'
1318 .pinyin$ = pinyin2numbers.numberstext$
1322 procedure readPinyin .currentWord
1323 call readDisplayPinyin '.currentWord'
1324 .character$ = readDisplayPinyin.character$
1325 .pinyin$ = replace_regex$(readDisplayPinyin.pinyin$, ".+", "\L&", 0)
1326 .pinyin$ = replace_regex$(.pinyin$, "[\\'\\` ]", "", 0)
1327 # Remove anything that is objectionable
1328 .pinyin$ = replace_regex$(.pinyin$, "[^a-zA-Z0-9_']", "", 0)
1332 include ToneProt/SGC_ToneProt.praat
1333 include ToneProt/DrawToneContour.praat
1334 include ToneProt/HumToneContour.praat
1335 include ToneProt/ToneRecognition.praat
1336 include ToneProt/ToneScript.praat
1337 include ToneProt/ToneRules.praat