2 # Desc: Convert IPA string into audio file
4 #==BEGIN Define script parameters==
5 #===BEGIN Initialize variables===
8 scriptName
="bkipas"; # Define basename of script file.
9 scriptVersion
="0.1.0"; # Define version of script.
10 scriptTimeStart
="$(date +%Y%m%dT%H%M%S.%N)"; # YYYYmmddTHHMMSS.NNNNNNNNN
11 scriptURL
="https://zdv2.bktei.com/gitweb/baltakatei-exdev.git"; # Define website hosting this script.
12 scriptHostname
=$
(hostname
); # Save hostname of system running this script.
13 PATH
="$HOME/.local/bin:$PATH"; # Add "$(systemd-path user-binaries)" path in case user apps saved there
16 declare -Ag appRollCall
# Associative array for storing app status
17 declare -Ag fileRollCall
# Associative array for storing file status
18 declare -Ag dirRollCall
# Associative array for storing dir status
21 optionVerbose
=""; optionOutputDir
=""; optionInputString
=""; argStrIn
=""; argDirOut
=""; pathOut
="";
23 #===END Initialize variables===
24 #===BEGIN Declare local script functions===
27 # Initialize variables and functions
28 yell
() { echo "$0: $*" >&2; } #o Yell, Die, Try Three-Fingered Claw technique
29 die
() { yell
"$*"; exit 111; } #o Ref/Attrib: https://stackoverflow.com/a/25515370
30 try
() { "$@" || die
"cannot $*"; } #o
32 # Description: Prints verbose message ("vbm") to stderr if optionVerbose is set to "true".
33 # Usage: vbm "DEBUG :verbose message here"
38 # Depends: bash 5.0.3, echo 8.30, date 8.30
40 if [ "$optionVerbose" = "true" ]; then
41 functionTime
=$
(date --iso-8601=ns
); # Save current time in nano seconds.
42 echo "[$functionTime]:$0:""$*" 1>&2; # Display argument text.
46 return 0; # Function finished.
47 } # Displays message if optionVerbose true
49 while [ ! $# -eq 0 ]; do # While number of arguments ($#) is not (!) equal to (-eq) zero (0).
51 -v |
--verbose) optionVerbose
="true"; vbm
"DEBUG :Verbose mode enabled.";; # Enable verbose mode.
52 -h |
--help) showUsage
; exit 1;; # Display usage.
53 --version) showVersion
; exit 1;; # Show version.
54 -i |
--input-string) optionInputString
="true"; if [[ ! -z "$2" ]]; then argStrIn
="$2"; vbm
"DEBUG :argStrIn:$argStrIn"; shift; fi ;; # Identify input string.
55 -o |
--output-dir) optionOutputDir
="true"; if [[ -d "$2" ]]; then argDirOut
="$2"; vbm
"DEBUG :argDirOut:$argDirOut"; shift; fi ;; # Define output directory.
56 *) yell
"ERROR: Unrecognized argument: $1"; yell
"STATUS:All arguments:$*"; exit 1;; # Handle unrecognized options.
60 } # Argument Processing
62 # Desc: If arg is a command, save result in assoc array 'appRollCall'
63 # Usage: checkapp arg1 arg2 arg3 ...
65 # Input: global assoc. array 'appRollCall'
66 # Output: adds/updates key(value) to global assoc array 'appRollCall'
72 if command -v "$arg" 1>/dev
/null
2>&1; then # Check if arg is a valid command
73 appRollCall
[$arg]="true";
74 if ! [ "$returnState" = "false" ]; then returnState
="true"; fi;
76 appRollCall
[$arg]="false"; returnState
="false";
80 #===Determine function return code===
81 if [ "$returnState" = "true" ]; then
86 } # Check that app exists
88 # Desc: If arg is a file path, save result in assoc array 'fileRollCall'
89 # Usage: checkfile arg1 arg2 arg3 ...
91 # Input: global assoc. array 'fileRollCall'
92 # Output: adds/updates key(value) to global assoc array 'fileRollCall';
93 # Output: returns 0 if app found, 1 otherwise
99 if [ -f "$arg" ]; then
100 fileRollCall
["$arg"]="true";
101 if ! [ "$returnState" = "false" ]; then returnState
="true"; fi;
103 fileRollCall
["$arg"]="false"; returnState
="false";
107 #===Determine function return code===
108 if [ "$returnState" = "true" ]; then
113 } # Check that file exists
115 # Desc: If arg is a dir path, save result in assoc array 'dirRollCall'
116 # Usage: checkdir arg1 arg2 arg3 ...
118 # Input: global assoc. array 'dirRollCall'
119 # Output: adds/updates key(value) to global assoc array 'dirRollCall';
120 # Output: returns 0 if app found, 1 otherwise
121 # Depends: Bash 5.0.3
126 if [ -d "$arg" ]; then
127 dirRollCall
["$arg"]="true";
128 if ! [ "$returnState" = "false" ]; then returnState
="true"; fi
130 dirRollCall
["$arg"]="false"; returnState
="false";
134 #===Determine function return code===
135 if [ "$returnState" = "true" ]; then
140 } # Check that dir exists
142 # Desc: Displays missing apps, files, and dirs
143 # Usage: displayMissing
145 # Input: associative arrays: appRollCall, fileRollCall, dirRollCall
146 # Output: stderr: messages indicating missing apps, file, or dirs
147 # Depends: bash 5, checkAppFileDir()
148 local missingApps value appMissing missingFiles fileMissing
149 local missingDirs dirMissing
151 #==BEGIN Display errors==
152 #===BEGIN Display Missing Apps===
153 missingApps
="Missing apps :";
154 #for key in "${!appRollCall[@]}"; do echo "DEBUG :$key => ${appRollCall[$key]}"; done
155 for key
in "${!appRollCall[@]}"; do
156 value
="${appRollCall[$key]}";
157 if [ "$value" = "false" ]; then
158 #echo "DEBUG :Missing apps: $key => $value";
159 missingApps
="$missingApps""$key ";
163 if [ "$appMissing" = "true" ]; then # Only indicate if an app is missing.
164 echo "$missingApps" 1>&2;
167 #===END Display Missing Apps===
169 #===BEGIN Display Missing Files===
170 missingFiles
="Missing files:";
171 #for key in "${!fileRollCall[@]}"; do echo "DEBUG :$key => ${fileRollCall[$key]}"; done
172 for key
in "${!fileRollCall[@]}"; do
173 value
="${fileRollCall[$key]}";
174 if [ "$value" = "false" ]; then
175 #echo "DEBUG :Missing files: $key => $value";
176 missingFiles
="$missingFiles""$key ";
180 if [ "$fileMissing" = "true" ]; then # Only indicate if an app is missing.
181 echo "$missingFiles" 1>&2;
184 #===END Display Missing Files===
186 #===BEGIN Display Missing Directories===
187 missingDirs
="Missing dirs:";
188 #for key in "${!dirRollCall[@]}"; do echo "DEBUG :$key => ${dirRollCall[$key]}"; done
189 for key
in "${!dirRollCall[@]}"; do
190 value
="${dirRollCall[$key]}";
191 if [ "$value" = "false" ]; then
192 #echo "DEBUG :Missing dirs: $key => $value";
193 missingDirs
="$missingDirs""$key ";
197 if [ "$dirMissing" = "true" ]; then # Only indicate if an dir is missing.
198 echo "$missingDirs" 1>&2;
201 #===END Display Missing Directories===
203 #==END Display errors==
204 } # Display missing apps, files, dirs
206 yell
"$scriptVersion"
208 Copyright (C) 2020 Steven Baltakatei Sandoval
209 License GPLv3: GNU GPL version 3
210 This is free software; you are free to change and redistribute it.
211 There is NO WARRANTY, to the extent permitted by law.
213 lexconvert (https://github.com/ssb22/lexconvert commit 64a4837)
214 Copyright (C) 2020 Silas S. Brown
215 License GPLv3: GNU GPL version 3
217 } # Display script version.
225 Display help information.
227 Display script version.
229 Display debugging info.
230 -i, --input-string [ str input ]
231 Specify input IPA string.
232 -o, --output-dir [ path dir ]
233 Specify output directory path.
236 bkipas -i "təˈmeɪtoʊ" # same as: echo "[[t@'meItoU]]" | espeak
237 bkipas -i "təˈmeɪtoʊ" -o /tmp/
239 } # Display information on how to use this script.
242 # Desc: Main function
245 # Outputs: file (pathout_tar)
248 # Debug:Get function name
251 vbm
"STATUS:$fn:Started function main().";
253 processArguments
"$@";
255 # Specify expected lexconvert.py path
256 pathLexConvert
="./bkipas.d/lexconvert.py" && vbm
"DEBUG :$fn:pathLexConvert:$pathLexConvert";
257 ## Note: lexconvert.py converts IPA into eSpeak phoneme mneumonics
258 ## See https://github.com/ssb22/lexconvert
259 ## See https://github.com/espeak-ng/espeak-ng/issues/539#issuecomment-536192362
261 # Check vital apps, files, dirs
262 if ! checkapp
sed python3 espeak oggenc
&& ! checkfile
"$pathLexConvert"; then
263 yell
"ERROR:$fn:Critical components missing.";
264 displayMissing
; yell
"Exiting."; exit 1; fi;
266 # Process input string
268 strIn
="$(echo "$argStrIn" | sed 's/\///g')";
269 ## Check for empty string
270 if [[ -z "$strIn" ]]; then yell
"ERROR:No IPA string provided."; exit 1; fi;
272 # Determine output file name
273 if [[ "$optionOutputDir" = "true" ]]; then
274 #pathOut="$argDirOut/$scriptTimeStart".ogg && vbm "DEBUG :$fn:pathOut:$pathOut";
275 pathOut
="$argDirOut/$strIn".ogg
&& vbm
"DEBUG :$fn:pathOut:$pathOut";
277 #pathOut="$(pwd)/$scriptTimeStart".ogg && vbm "DEBUG :$fn:pathOut:$pathOut";
278 pathOut
="$(pwd)/$strIn".ogg
&& vbm
"DEBUG :$fn:pathOut:$pathOut";
281 # Generate espeak phoneme mneumonic
282 espeakInput
="$(python3 "$pathLexConvert" --phones2phones unicode-ipa espeak "$strIn")" && vbm
"DEBUG :$fn:espeakInput:$espeakInput";
284 # Output pronunciation
285 if [[ "$optionOutputDir" = "true" ]]; then
286 ## Write to file if -o specified
287 echo "$espeakInput" | espeak
--stdout | oggenc
-o "$pathOut" - ;
289 ## Speak pronunciation via espeak
290 echo "$espeakInput" | espeak
;
295 #===END Declare local script functions===
296 #==END Define script parameters==
298 #==BEGIN Perform work and exit==
299 main
"$@" # Run main function.
301 #==END Perform work and exit==
303 # Author: Steven Baltakatei Sandoval;