4 # Intializing Praat script
6 # SpeakGoodChinese: InitializeSGC2.praat defines and sets the global variables
7 # and loads general SGC2 code
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
29 # Do not store these variables as preferences
30 sgc.nonPreferences$ = " config.savePerf config.openPerf config.clearSummary config.audioName "
32 # Information for logging
33 currentDate$ = date$()
34 dateYear$ = right$(currentDate$, length(currentDate$) - rindex(currentDate$, " "))
35 logtimeStamp$ = replace_regex$(currentDate$, "[^a-zA-Z0-9\-_]", "-", 0)
36 currentLogDirectory$ = ""
37 feedbackTablePrefix$ = "Feedback"
38 feedbackTableName$ = ""
43 yFeedback = yWordlist + 5
44 yPinyin = yFeedback + 10
45 yContour = yPinyin + 15
46 wipeContourArea$ = "demo Paint rectangle... White 20 80 'yContour' 100"
47 wipePinyinArea$ = "demo Paint rectangle... White 20 80 'yPinyin' 'yContour'"
48 wipeFeedbackArea$ = "demo Paint rectangle... White 0 100 'yFeedback' 'yPinyin'"
49 wipeWordlistArea$ = "demo Paint rectangle... White 20 80 'yWordlist' 'yFeedback'"
51 # Pop-Up window colors
52 sgc2.popUp_bordercolor$ = "{0.5,0.5,1}"
53 sgc2.popUp_backgroundcolor$ = "{0.9,0.9,1}"
55 # Initialize parameters
71 config.deleteWordlist = -1
72 config.displayNumbers = 1
73 config.displayPinyin = 1
74 config.displayChar = 0
75 config.displayTrans = 1
76 config.useSoundExample = 1
77 config.synthesis$ = "_DISABLED_"
78 config.input$ = "Microphone"
79 config.showBackground = 1
80 sgc2.noiseThresshold = -30
84 config.clearSummary = 0
85 config.audioName$ = ""
88 mainPage.saveAudio$ = ""
90 sgc_ToneProt.minimumPitch = 40
91 sgc_ToneProt.maximumPitch = 600
93 # Platform dependent settings
94 if macintosh or windows
95 config.displayChar = 1
96 config.displayNumbers = 0
98 if windows and endsWith(build_SHA$, " XP")
99 config.displayChar = 0
100 config.displayNumbers = 0
103 config.displayChar = 0
104 config.displayNumbers = 1
108 samplingFrequency = 44100
110 samplingFrequency = 44100
112 samplingFrequency = 44100
117 config.language$ = "EN"
118 config.register = 249
119 preferencesAppFile$ = preferencesAppDir$+"/sgc2rc.txt"
120 preferencesLogDir$ = "'preferencesAppDir$'/log"
121 preferencesTableDir$ = "'preferencesAppDir$'/Data"
122 sgc2wordlists$ = "'preferencesAppDir$'/wordlists"
123 localWordlistDir$ = sgc2wordlists$
125 # Global word lists must be installed BY THE ADMINISTRATOR
126 # This means, create the directory 'globalwordlists$' and
127 # fill it with wordlist directories containing wordlist.Table
128 # and audio files. They can be copied from a local directory.
129 globalwordlists$ = ""
130 globaltablelists$ = ""
133 globalwordlists$ = "/etc/'sgc2.demoAppName$'/wordlists"
134 globaltablelists$ = "/etc/'sgc2.demoAppName$'/Data"
135 globalTTSdir$ = "/etc/'sgc2.demoAppName$'/TTS"
137 globalwordlists$ = "/Library/Preferences/'sgc2.demoAppName$'/wordlists"
138 globaltablelists$ = "/Library/Preferences/'sgc2.demoAppName$'/Data"
139 globalTTSdir$ = "/Library/Preferences/'sgc2.demoAppName$'/TTS"
141 globalwordlists$ = "C:/Documents and Settings/All Users/Application Data/'sgc2.demoAppName$'/wordlists"
142 globaltablelists$ = "C:/Documents and Settings/All Users/Application Data/'sgc2.demoAppName$'/Data"
143 globalTTSdir$ = "C:/Documents and Settings/All Users/Application Data/'sgc2.demoAppName$'/TTS"
145 sgc2.synthesizer = -1
146 # Define a Praat TTS command that will set sgc2.synthesizer
147 sgc2.normalTTScommand$ = "call create_default_TTS Mandarin f4 10000 0.01 50 100 95 no IPA"
148 sgc2.advancedTTScommand$ = "call create_default_TTS Mandarin f4 10000 0.01 50 70 125 no IPA"
149 sgc2.alignedTextGrid = -1
151 ##############################################################
153 config.shuffleLists = 1
155 defaultFont$ = "Helvetica"
158 # Set up directories if they do not exist already
159 call set_up_directories
161 # Get saved preferences
162 call read_preferences ""
165 speakCommandDir$ = "'preferencesAppDir$'/TTS"
166 speakCommandFile$ = ""
169 # Set inital language
170 call set_language 'config.language$'
173 call load_word_list "'localWordlistDir$'" 0
175 # Set up evaluation table
176 initialiseSGC2.toneevaluation_table$ = ""
177 call initialize_toneevaluation_tables
182 ###############################################################
184 # Obligatory procedures
186 ###############################################################
187 # Initialize Demo Window
188 procedure init_window
190 demo Line width... 'defaultLineWidth'
192 call set_font_size 'defaultFontSize'
195 # If there is no recorded sound, try to read stored recording
196 if recordedSound$ = "" and sgc.saveAudio$ <> ""
198 select Table 'wordlist$'
199 if te.currentWord > 0 and te.currentWord <= te.numberOfWords
200 sgc.pinyin$ = Get value... 'te.currentWord' Pinyin
201 .outputName$ = "'sgc.saveAudio$'/'sgc.pinyin$'.wav"
202 if fileReadable(.outputName$)
203 te.recordedSound = Read from file: .outputName$
204 recordedSound$ = selected$("Sound")
207 # Set config.audioName
208 .tmp$ = replace_regex$(sgc.saveAudio$, "[^/]+/?$", "", 0)
209 config.audioName$ = replace$(sgc.saveAudio$, .tmp$, "", 0)
215 # Set mainPage.saveAudio$ grade
216 call set_grade_display 'sgc.pinyin$'
220 .windowTitle$ = replace$(wordlistName$, "_", " ", 0)
221 call set_window_title 'buttons$' '.windowTitle$'
222 # Display the word-list
224 # Wipe screen and draw background
225 call wipeArea 'wipeContourArea$'
226 if config.showBackground
227 call draw_background Background
229 # Define buttons in a table
235 call draw_tone_contour
237 call paint_saveAudio_light
242 # Make sure all Preferences directories are available
243 procedure set_up_directories
244 .dirPath$ = "'preferencesAppDir$'"
245 createDirectory(.dirPath$)
246 .dirPath$ > '.dirPath$'/directory.txt
247 createDirectory("'.dirPath$'/wordlists")
248 .dirPath$ > '.dirPath$'/wordlists/directory.txt
249 createDirectory("'.dirPath$'/pitchmodels")
250 .dirPath$ > '.dirPath$'/pitchmodels/directory.txt
251 createDirectory("'.dirPath$'/log")
252 .dirPath$ > '.dirPath$'/log/directory.txt
253 createDirectory("'.dirPath$'/TTS")
254 .dirPath$ > '.dirPath$'/TTS/directory.txt
258 # Retrieve and store setting between sessions
260 procedure read_preferences .preferencesFile$
261 if not fileReadable(.preferencesFile$)
262 .preferencesFile$ = preferencesAppFile$
264 if fileReadable(.preferencesFile$)
265 Read from file... 'preferencesAppFile$'
266 .preferenceTable$ = selected$("Table")
267 .numPrefKeys = Get number of rows
268 for .row to .numPrefKeys
269 .variableName$ = Get value... '.row' Key
270 if variableExists(.variableName$)
271 .variableValue = Get value... '.row' Value
272 if .variableValue <> undefined
273 '.variableName$' = '.variableValue'
275 elsif variableExists(.variableName$+"$")
276 .variableValue$ = Get value... '.row' Value
277 .variableName$ = .variableName$+"$"
278 '.variableName$' = "'.variableValue$'"
282 select Table '.preferenceTable$'
287 procedure write_preferences .preferencesFile$
288 Create Table with column names... Preferences 0 Key Value
289 if index_regex(.preferencesFile$, "[a-zA-Z0-9]") <= 0
290 .preferencesFile$ = preferencesAppFile$
294 for .tableNum from 1 to 2
300 .varPrefix$ = replace_regex$(.table$, "^(.)", "\l\1", 0)
302 select Table '.table$'
303 .numTableRows = Get number of rows
304 for .tablerow to .numTableRows
305 select Table '.table$'
306 .label$ = Get value... '.tablerow' Label
307 .variableName$ = .varPrefix$+"."+(replace_regex$(.label$, "^(.)", "\l\1", 0))
308 .keyName$ = .variableName$
310 if sgc.nonPreferences$ <> "" and index(sgc.nonPreferences$, " '.variableName$' ")
312 elsif variableExists(.variableName$)
313 .value = '.variableName$'
315 elsif variableExists(.variableName$ + "$")
316 .variableName$ = .variableName$ + "$"
317 .value$ = '.variableName$'
318 elsif index(.variableName$, "_") > 0
319 .variableName$ = left$(.variableName$, rindex(.variableName$, "_") - 1)
320 .keyName$ = .variableName$
321 select Table Preferences
322 .prefRow = Search column... Key '.keyName$'
324 if variableExists(.variableName$)
325 .value = '.variableName$'
327 elsif variableExists(.variableName$ + "$")
328 .variableName$ = .variableName$ + "$"
329 .value$ = '.variableName$'
335 select Table Preferences
338 Set string value... '.row' Key '.keyName$'
339 Set string value... '.row' Value '.value$'
344 # Some extra settings
345 select Table Preferences
348 Set string value... '.row' Key wordlistDir
349 Set string value... '.row' Value 'localWordlistDir$'
351 select Table Preferences
354 Set string value... '.row' Key wordlistName
355 Set string value... '.row' Value 'wordlistName$'
357 select Table Preferences
358 Write to table file... '.preferencesFile$'
363 ###############################################################
365 # TTS (speech synthesis). Place commands in user info
368 # speakCommandDir$ = "'preferencesAppDir$'/TTS"
369 # speakCommandFile$ = ""
371 # Make sure sgc2.synthesizer is set!
372 procedure create_default_TTS .language$ .voice$ .samplefreq .gap .pitch_adj .pitch_range .words_per_minute .use_data$ .espeak_phones$
373 sgc2.synthesizer = Create SpeechSynthesizer... '.language$' '.voice$'
374 Set speech output settings... .samplefreq .gap .pitch_adj .pitch_range .words_per_minute '.use_data$' '.espeak_phones$'
378 if sgc2.synthesizer > 0
379 select sgc2.synthesizer
381 sgc2.synthesizer = -1
383 # Note, the TTScommand must set sgc2.synthesizer!
385 'sgc2.advancedTTScommand$'
387 'sgc2.normalTTScommand$'
391 .ttscommand$ = "speak"
395 .ttscommand$ = "espeak"
399 .ttscommand$ = "C:/Program Files/eSpeak/command_line/espeak.exe"
403 # Global TTS command has precedence
404 if fileReadable("'globalTTSdir$'/TTS_'.osName$'_command.txt")
405 speakCommandFile$ = "'globalTTSdir$'/TTS_'.osName$'_command.txt"
406 if config.synthesis$ = "_DISABLED_"
408 config.synthesis$ = "eSpeak"
412 # Local TTS command, if there is no global one
413 # Command does not exist yet, create it if eSpeak is installed
414 # Make sure to quote the path!
415 if speakCommandFile$ = ""
416 # Autodetect synthesizer command
417 # if not fileReadable("'speakCommandDir$'/TTS_'.osName$'_eSpeak_command.txt")
418 # .command_path$ = ""
420 # system_nocheck PATH=${PATH}:/opt/local/bin; bash -c -- 'which '.ttscommand$' > "'speakCommandDir$'/command_path.txt"'
421 # .command_path$ < 'speakCommandDir$'/command_path.txt
423 # system_nocheck PATH=${PATH};bash -c -- 'which '.ttscommand$' > "'speakCommandDir$'/command_path.txt"'
424 # .command_path$ < 'speakCommandDir$'/command_path.txt
426 # if fileReadable(.ttscommand$)
427 # .command_path$ = .ttscommand$
430 # # Remove any newlines
431 # .command_path$ = replace$(.command_path$, "'newline$'", "", 0)
433 # # Command path found
434 # if sgc2.synthesizer <= 0 and .command_path$ <> "" and fileReadable(.command_path$)
435 # deleteFile("'speakCommandDir$'/TTS_'.osName$'_eSpeak_command.txt")
436 # fileappend "'speakCommandDir$'/TTS_'.osName$'_eSpeak_command.txt"
437 # ...'.quote$''.ttscommand$''.quote$' -v zh+f4 -s 100 'newline$'
438 # speakCommandFile$ = "'speakCommandDir$'/TTS_'.osName$'_eSpeak_command.txt"
441 # if fileReadable("'speakCommandDir$'/TTS_'.osName$'_eSpeak_command.txt")
442 speakCommandFile$ = "'speakCommandDir$'/TTS_'.osName$'_eSpeak_command.txt"
444 deleteFile("'speakCommandDir$'/command_path.txt")
447 # Close off (other TTS maybe a later option)
448 if sgc2.synthesizer > 0 or (speakCommandFile$ <> "" and fileReadable(speakCommandFile$))
449 config.synthesis$ = "eSpeak"
453 ###############################################################
458 # initialiseSGC2.toneevaluation_table$ = ""
459 procedure initialize_toneevaluation_tables
461 if initialiseSGC2.toneevaluation_table$ != ""
462 select Table 'initialiseSGC2.toneevaluation_table$'
465 initialiseSGC2.toneevaluation_table$ = ""
467 if sgc.savePerf$ <> "" and fileReadable(sgc.savePerf$)
468 sgc2.performanceTable = Read Table from tab-separated file: sgc.savePerf$
469 Rename: "Performance"
472 sgc2.performanceTable = Create Table with column names... Performance 0 Pinyin Correct Wrong Total High Low Wide Narrow Unknown Commented Time
474 initialiseSGC2.toneevaluation_table$ = "Performance"
475 call get_toneevaluation_row Total
478 procedure get_toneevaluation_row .pinyin$
479 select Table 'initialiseSGC2.toneevaluation_table$'
480 .row = Search column... Pinyin '.pinyin$'
483 .row = Get number of rows
484 Set string value... '.row' Pinyin '.pinyin$'
485 Set numeric value... '.row' Correct 0
486 Set numeric value... '.row' Wrong 0
487 Set numeric value... '.row' Total 0
488 Set numeric value... '.row' High 0
489 Set numeric value... '.row' Low 0
490 Set numeric value... '.row' Wide 0
491 Set numeric value... '.row' Narrow 0
492 Set numeric value... '.row' Unknown 0
493 Set numeric value... '.row' Commented 0
494 Set numeric value... '.row' Time 0
496 .row = Search column... Pinyin '.pinyin$'
500 procedure increment_toneevaluation_in_row .row .column$
501 select Table 'initialiseSGC2.toneevaluation_table$'
502 .tmp = Get value... '.row' '.column$'
504 Set numeric value... '.row' '.column$' '.tmp'
508 Set string value: .row, "Time", .dateTime$
512 # Update existing performance file with toneevaluation
513 procedure update_toneevaluation_file
514 if sgc.savePerf$ <> "" and fileReadable(sgc.savePerf$) and initialiseSGC2.toneevaluation_table$ <> ""
515 select Table 'initialiseSGC2.toneevaluation_table$'
516 Write to table file... 'sgc.savePerf$'
520 procedure increment_toneevaluation_value .pinyin$ .column$
521 call get_toneevaluation_row '.pinyin$'
522 .row = get_toneevaluation_row.row
523 call increment_toneevaluation_in_row '.row' '.column$'
525 call get_toneevaluation_row Total
526 .row = get_toneevaluation_row.row
527 call increment_toneevaluation_in_row '.row' '.column$'
530 procedure add_feedback_to_toneevaluation .table$
531 select Table '.table$'
532 .line1$ = Get value... 1 Text
533 .line2$ = Get value... 2 Text
534 .label$ = Get value... 3 Text
539 .tones$ = replace_regex$(left$(.line1$, rindex(.line1$, ":")), "[^0-9]", "", 0)
540 .recognized$ = replace_regex$(right$(.line1$, length(.line1$)-rindex(.line1$, ":")), "[^0-9]", "", 0)
543 call increment_toneevaluation_value 'sgc.pinyin$' Total
544 if .tones$ = .recognized$
545 call increment_toneevaluation_value 'sgc.pinyin$' Correct
547 call increment_toneevaluation_value 'sgc.pinyin$' Wrong
549 if index_regex(.label$, "(Correct|Wrong)") <= 0
550 call increment_toneevaluation_value 'sgc.pinyin$' '.label$'
551 call increment_toneevaluation_value 'sgc.pinyin$' Commented
554 # Update performance table when SaveAudio is on
556 call update_toneevaluation_file
560 procedure setGrade .grade$
561 select Table 'wordlist$'
562 if recordedSound$ <> "" and sgc.pinyin$ <> ""
563 call get_toneevaluation_row 'sgc.pinyin$'
564 .row = get_toneevaluation_row.row
565 select Table 'initialiseSGC2.toneevaluation_table$'
566 .col = Get column index... Grade
568 Insert column... 2 Grade
571 Set numeric value: .row, "Grade", '.grade$'
572 .numRows = Get number of rows
575 for .r from 2 to .numRows
576 .tmp = Get value: .r, "Grade"
584 .meanGrade = .sumGrade / .sumN
586 Set numeric value: 1, "Grade", .meanGrade
588 # Store current performance table
589 call update_toneevaluation_file
593 # Set mainPage.saveAudio$ to Grade
594 procedure set_grade_display .pinyin$
595 mainPage.saveAudio$ = ""
596 select Table 'initialiseSGC2.toneevaluation_table$'
598 .col = Get column index: "Grade"
599 if .pinyin$ <> "" and .col > 0
600 call get_toneevaluation_row '.pinyin$'
601 .row = get_toneevaluation_row.row
603 .grade$ = Get value: .row, "Grade"
604 if index_regex(.grade$, "[0-9]") <= 0
610 mainPage.saveAudio$ = .grade$
614 ###############################################################
616 # Miscelaneous procedures
618 ###############################################################
621 procedure synthesize_sound .pinyin$
623 if speakCommandFile$ <> "" and fileReadable(speakCommandFile$)
624 .command$ < 'speakCommandFile$'
625 .command$ = replace$(.command$, "'newline$'", " ", 0)
627 system_nocheck PATH=${PATH}:/usr/local/bin:/opt/local/bin; bash -rc -- ''.command$' "'.pinyin$'"'
629 system_nocheck bash -rc -- ''.command$' "'.pinyin$'"'
631 system_nocheck call '.command$' "'.pinyin$'"'
633 elsif sgc2.synthesizer > 0
634 select sgc2.synthesizer
635 Play text... '.pinyin$'
639 procedure align_recordedSound .pinyin$
640 if 0 and sgc2.synthesizer > 0 and recordedSound$ <> ""
641 select Sound 'recordedSound$'
642 .recordedTextGrid = To TextGrid... pinyin
643 Set interval text... 1 1 '.pinyin$'
644 select sgc2.synthesizer
645 plus Sound 'recordedSound$'
646 plus .recordedTextGrid
647 sgc2.alignedTextGrid = nowarn noprogress To TextGrid (align,trim)... 1 1 1 -35 0.1 0.1 0.08
648 Rename... AlignedTextGrid
649 select .recordedTextGrid