glaemscribe 1.1.14 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/bin/glaemscribe +19 -15
- data/glaemresources/charsets/cirth_ds.cst +205 -0
- data/glaemresources/charsets/sarati_eldamar.cst +256 -0
- data/glaemresources/charsets/tengwar_ds_annatar.cst +546 -0
- data/glaemresources/charsets/tengwar_ds_eldamar.cst +535 -0
- data/glaemresources/charsets/tengwar_ds_elfica.cst +551 -0
- data/glaemresources/charsets/tengwar_ds_parmaite.cst +534 -0
- data/glaemresources/charsets/tengwar_ds_sindarin.cst +531 -0
- data/glaemresources/charsets/tengwar_freemono.cst +217 -0
- data/glaemresources/charsets/tengwar_guni_annatar.cst +628 -0
- data/glaemresources/charsets/tengwar_guni_eldamar.cst +618 -0
- data/glaemresources/charsets/tengwar_guni_elfica.cst +620 -0
- data/glaemresources/charsets/tengwar_guni_parmaite.cst +621 -0
- data/glaemresources/charsets/tengwar_guni_sindarin.cst +617 -0
- data/glaemresources/charsets/tengwar_telcontar.cst +218 -0
- data/glaemresources/charsets/unicode_gothic.cst +64 -0
- data/glaemresources/charsets/unicode_runes.cst +121 -0
- data/glaemresources/modes/{adunaic.glaem → adunaic-tengwar-glaemscrafu.glaem} +14 -2
- data/glaemresources/modes/{blackspeech.glaem → blackspeech-tengwar-general_use.glaem} +12 -2
- data/glaemresources/modes/japanese-tengwar.glaem +771 -0
- data/glaemresources/modes/{khuzdul.glaem → khuzdul-cirth-moria.glaem} +4 -1
- data/glaemresources/modes/{futhorc.glaem → old_english-futhorc.glaem} +0 -0
- data/glaemresources/modes/{mercian.glaem → old_english-tengwar-mercian.glaem} +22 -12
- data/glaemresources/modes/{westsaxon.glaem → old_english-tengwar-westsaxon.glaem} +20 -11
- data/glaemresources/modes/{futhark-runicus.glaem → old_norse-futhark-runicus.glaem} +0 -0
- data/glaemresources/modes/{futhark-younger.glaem → old_norse-futhark-younger.glaem} +0 -0
- data/glaemresources/modes/{quenya.glaem → quenya-tengwar-classical.glaem} +32 -50
- data/glaemresources/modes/raw-tengwar.glaem +46 -23
- data/glaemresources/modes/{rlyehian.glaem → rlyehian-tengwar.glaem} +14 -3
- data/glaemresources/modes/{sindarin-daeron.glaem → sindarin-cirth-daeron.glaem} +55 -14
- data/glaemresources/modes/{sindarin-beleriand.glaem → sindarin-tengwar-beleriand.glaem} +154 -28
- data/glaemresources/modes/{sindarin.glaem → sindarin-tengwar-general_use.glaem} +86 -25
- data/glaemresources/modes/{telerin.glaem → telerin-tengwar-glaemscrafu.glaem} +16 -6
- data/glaemresources/modes/{westron.glaem → westron-tengwar-glaemscrafu.glaem} +18 -8
- data/lib/api/charset.rb +67 -7
- data/lib/api/charset_parser.rb +7 -0
- data/lib/api/constants.rb +3 -4
- data/lib/api/fragment.rb +26 -5
- data/lib/api/if_tree.rb +70 -8
- data/lib/api/macro.rb +40 -0
- data/lib/api/mode.rb +35 -13
- data/lib/api/mode_parser.rb +106 -12
- data/lib/api/object_additions.rb +23 -1
- data/lib/api/option.rb +17 -2
- data/lib/api/post_processor/resolve_virtuals.rb +25 -9
- data/lib/api/resource_manager.rb +1 -0
- data/lib/api/rule_group.rb +170 -26
- data/lib/api/sheaf_chain_iterator.rb +1 -1
- data/lib/api/transcription_processor.rb +3 -3
- data/lib/api/tts.rb +51 -0
- data/lib/glaemscribe.rb +34 -31
- data/lib_espeak/espeakng.for.glaemscribe.nowasm.sync.js +21 -0
- data/lib_espeak/glaemscribe_tts.js +365 -0
- metadata +67 -21
data/lib/api/object_additions.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# From http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/43424
|
2
2
|
class Object
|
3
|
+
=begin
|
3
4
|
def deep_clone
|
4
5
|
return @deep_cloning_obj if @deep_cloning
|
6
|
+
|
5
7
|
@deep_cloning_obj = clone
|
6
8
|
@deep_cloning_obj.instance_variables.each do |var|
|
7
9
|
val = @deep_cloning_obj.instance_variable_get(var)
|
@@ -19,4 +21,24 @@ class Object
|
|
19
21
|
@deep_cloning_obj = nil
|
20
22
|
deep_cloning_obj
|
21
23
|
end
|
22
|
-
end
|
24
|
+
=end
|
25
|
+
|
26
|
+
def deep_clone(cache={})
|
27
|
+
return cache[self] if cache.key?(self)
|
28
|
+
|
29
|
+
copy = clone()
|
30
|
+
cache[self] = copy
|
31
|
+
|
32
|
+
copy.instance_variables.each do |var|
|
33
|
+
val = instance_variable_get(var)
|
34
|
+
begin
|
35
|
+
val = val.deep_clone(cache)
|
36
|
+
rescue TypeError
|
37
|
+
next
|
38
|
+
end
|
39
|
+
copy.instance_variable_set(var, val)
|
40
|
+
end
|
41
|
+
|
42
|
+
return copy
|
43
|
+
end
|
44
|
+
end
|
data/lib/api/option.rb
CHANGED
@@ -25,24 +25,29 @@ module Glaemscribe
|
|
25
25
|
|
26
26
|
class Option
|
27
27
|
attr_reader :mode
|
28
|
+
attr_reader :line
|
28
29
|
attr_reader :name
|
29
30
|
attr_reader :type
|
30
31
|
attr_reader :default_value_name
|
31
32
|
attr_reader :values
|
33
|
+
|
34
|
+
attr_accessor :is_radio
|
32
35
|
|
33
|
-
|
34
36
|
class Type
|
35
37
|
ENUM = "ENUM"
|
36
38
|
BOOL = "BOOL"
|
37
39
|
end
|
38
40
|
|
39
|
-
def initialize(mode,
|
41
|
+
def initialize(mode, name, default_value_name, values, line, visibility = nil)
|
40
42
|
@mode = mode
|
41
43
|
@name = name
|
42
44
|
@default_value_name = default_value_name
|
43
45
|
@type = (values.keys.count == 0)?(Type::BOOL):(Type::ENUM)
|
44
46
|
@values = values
|
45
47
|
@visibility = visibility
|
48
|
+
@line = line
|
49
|
+
@value_to_names = {}
|
50
|
+
@values.each { |vname, val| @value_to_names[val] = vname }
|
46
51
|
end
|
47
52
|
|
48
53
|
def default_value
|
@@ -63,6 +68,16 @@ module Glaemscribe
|
|
63
68
|
end
|
64
69
|
end
|
65
70
|
|
71
|
+
def value_name_for_value(value)
|
72
|
+
if @type == Type::BOOL
|
73
|
+
return "true" if value == true || value == "true"
|
74
|
+
return "false" if value == false || value == "false"
|
75
|
+
return nil
|
76
|
+
else
|
77
|
+
return @value_to_names[value]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
66
81
|
def visible?
|
67
82
|
if_eval = Eval::Parser.new()
|
68
83
|
|
@@ -50,19 +50,35 @@ module Glaemscribe
|
|
50
50
|
# Try to replace
|
51
51
|
last_trigger = @last_triggers[c]
|
52
52
|
if last_trigger != nil
|
53
|
-
new_tokens[idx] = last_trigger.names.first
|
53
|
+
new_tokens[idx] = last_trigger.names.first # Take the first name of the non-virtual replacement.
|
54
|
+
token = new_tokens[idx] # Consider the token replaced, being itself a potential trigger for further virtuals (cascading virtuals)
|
54
55
|
end
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
end
|
57
|
+
|
58
|
+
# Update states of virtual classes
|
59
|
+
charset.virtual_chars.each{|vc|
|
60
|
+
rc = vc[token]
|
61
|
+
@last_triggers[vc] = rc if rc != nil
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def apply_sequences(charset,tokens)
|
66
|
+
ret = []
|
67
|
+
tokens.each { |token|
|
68
|
+
c = charset[token]
|
69
|
+
if c && c.sequence?
|
70
|
+
ret += c.sequence
|
71
|
+
else
|
72
|
+
ret << token
|
73
|
+
end
|
74
|
+
}
|
75
|
+
ret
|
62
76
|
end
|
63
77
|
|
64
78
|
def apply(tokens,charset)
|
65
|
-
|
79
|
+
# Apply sequence chars
|
80
|
+
tokens = apply_sequences(charset,tokens)
|
81
|
+
|
66
82
|
# Clone the tokens so that we can perform ligatures AND diacritics without interferences
|
67
83
|
new_tokens = tokens.clone
|
68
84
|
|
data/lib/api/resource_manager.rb
CHANGED
data/lib/api/rule_group.rb
CHANGED
@@ -22,35 +22,92 @@
|
|
22
22
|
|
23
23
|
module Glaemscribe
|
24
24
|
module API
|
25
|
+
|
26
|
+
class RuleGroupVar
|
27
|
+
attr_reader :name, :value
|
28
|
+
|
29
|
+
def initialize(name, value, is_pointer)
|
30
|
+
@name = name
|
31
|
+
@value = value
|
32
|
+
@is_pointer = is_pointer
|
33
|
+
end
|
34
|
+
|
35
|
+
def pointer?
|
36
|
+
is_pointer
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
25
40
|
class RuleGroup
|
26
41
|
|
27
|
-
VAR_NAME_REGEXP
|
28
|
-
|
29
|
-
|
30
|
-
|
42
|
+
VAR_NAME_REGEXP = /{([0-9A-Z_]+)}/
|
43
|
+
UNICODE_VAR_NAME_REGEXP_IN = /^UNI_([0-9A-F]+)$/
|
44
|
+
UNICODE_VAR_NAME_REGEXP_OUT = /{UNI_([0-9A-F]+)}/
|
45
|
+
|
46
|
+
VAR_DECL_REGEXP = /^\s*{([0-9A-Z_]+)}\s+===\s+(.+?)\s*$/
|
47
|
+
POINTER_VAR_DECL_REGEXP = /^\s*{([0-9A-Z_]+)}\s+<=>\s+(.+?)\s*$/
|
48
|
+
RULE_REGEXP = /^\s*(.*?)\s+-->\s+(.+?)\s*$/
|
49
|
+
|
50
|
+
CROSS_SCHEMA_REGEXP = /[0-9]+(\s*,\s*[0-9]+)*/
|
51
|
+
|
52
|
+
CROSS_RULE_REGEXP = /^\s*(.*?)\s+-->\s+(#{CROSS_SCHEMA_REGEXP}|#{VAR_NAME_REGEXP}|identity)\s+-->\s+(.+?)\s*$/
|
31
53
|
|
32
|
-
attr_reader :root_code_block, :name, :mode, :in_charset, :rules
|
54
|
+
attr_reader :root_code_block, :name, :mode, :in_charset, :rules, :macros
|
33
55
|
|
34
56
|
def initialize(mode,name)
|
35
57
|
@name = name
|
36
58
|
@mode = mode
|
59
|
+
@macros = {}
|
37
60
|
@root_code_block = IfTree::CodeBlock.new
|
38
61
|
end
|
39
62
|
|
40
|
-
def add_var(var_name, value)
|
41
|
-
@vars[var_name] = value
|
63
|
+
def add_var(var_name, value, is_pointer)
|
64
|
+
@vars[var_name] = RuleGroupVar.new(var_name, value, is_pointer)
|
42
65
|
end
|
43
|
-
|
66
|
+
|
44
67
|
# Replace all vars in expression
|
45
|
-
def apply_vars(line, string)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
68
|
+
def apply_vars(line, string, allow_unicode_vars=false)
|
69
|
+
|
70
|
+
ret = string
|
71
|
+
stack_depth = 0
|
72
|
+
had_replacements = true
|
73
|
+
|
74
|
+
while had_replacements
|
75
|
+
|
76
|
+
had_replacements = false
|
77
|
+
ret = ret.gsub(VAR_NAME_REGEXP) { |cap_var|
|
78
|
+
vname = $1
|
79
|
+
v = @vars[vname]
|
80
|
+
if !v
|
81
|
+
if vname =~ UNICODE_VAR_NAME_REGEXP_IN
|
82
|
+
# A unicode variable.
|
83
|
+
if allow_unicode_vars
|
84
|
+
# Just keep this variable intact, it will be replaced at the last moment of the parsing
|
85
|
+
rep = cap_var
|
86
|
+
else
|
87
|
+
@mode.errors << Glaeml::Error.new(line, "In expression: #{string}: making wrong use of unicode variable: #{cap_var}. Unicode vars can only be used in source members of a rule or in the definition of another variable.")
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
else
|
91
|
+
@mode.errors << Glaeml::Error.new(line, "In expression: #{string}: failed to evaluate variable: #{cap_var}.")
|
92
|
+
return nil
|
93
|
+
end
|
94
|
+
else
|
95
|
+
rep = v.value
|
96
|
+
# Only count replacements on non unicode vars
|
97
|
+
had_replacements = true
|
98
|
+
end
|
99
|
+
rep
|
100
|
+
}
|
101
|
+
stack_depth += 1
|
102
|
+
|
103
|
+
break if !had_replacements
|
104
|
+
|
105
|
+
if stack_depth > 16
|
106
|
+
@mode.errors << Glaeml::Error.new(line, "In expression: #{string}: evaluation stack overflow.")
|
50
107
|
return nil
|
51
108
|
end
|
52
|
-
|
53
|
-
|
109
|
+
end
|
110
|
+
|
54
111
|
ret
|
55
112
|
end
|
56
113
|
|
@@ -60,6 +117,58 @@ module Glaemscribe
|
|
60
117
|
term.code_lines.each{ |cl|
|
61
118
|
finalize_code_line(cl)
|
62
119
|
}
|
120
|
+
elsif(term.is_macro_deploy?)
|
121
|
+
|
122
|
+
# Ok this is a bit dirty but I don't want to rewrite the error managamenet
|
123
|
+
# So add an error and if it's still the last (meaning there were no error) one remove it
|
124
|
+
possible_error = Glaeml::Error.new(term.line, ">> Macro backtrace : #{term.macro.name}")
|
125
|
+
@mode.errors << possible_error
|
126
|
+
|
127
|
+
# First, test if variable is pushable
|
128
|
+
arg_values = []
|
129
|
+
term.macro.arg_names.each_with_index { |arg_name, i|
|
130
|
+
|
131
|
+
var_value = nil
|
132
|
+
|
133
|
+
if @vars[arg_name]
|
134
|
+
@mode.errors << Glaeml::Error.new(term.line, "Local variable #{arg_name} hinders a variable with the same name in this context. Use only local variable names in macros!")
|
135
|
+
else
|
136
|
+
# Evaluate local var
|
137
|
+
var_value_ex = term.arg_value_expressions[i]
|
138
|
+
var_value = apply_vars(term.line, var_value_ex, true)
|
139
|
+
|
140
|
+
if !var_value
|
141
|
+
@mode.errors << Glaeml::Error.new(term.line, "Thus, variable {#{var_name}} could not be declared.")
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
arg_values << {name: arg_name, val: var_value}
|
146
|
+
}
|
147
|
+
|
148
|
+
# We push local vars after the whole loop to avoid interferences between them when evaluating them
|
149
|
+
arg_values.each { |v|
|
150
|
+
if v[:val]
|
151
|
+
add_var(v[:name],v[:val],false)
|
152
|
+
end
|
153
|
+
}
|
154
|
+
|
155
|
+
descend_if_tree(term.macro.root_code_block, trans_options)
|
156
|
+
|
157
|
+
# Remove the local vars from the scope (only if they were leggit)
|
158
|
+
arg_values.each { |v|
|
159
|
+
if v[:val]
|
160
|
+
@vars[v[:name]] = nil
|
161
|
+
end
|
162
|
+
}
|
163
|
+
|
164
|
+
if mode.errors.last == possible_error
|
165
|
+
# Remove the error scope if there were no errors
|
166
|
+
mode.errors.pop
|
167
|
+
else
|
168
|
+
# Add another one to close the context
|
169
|
+
@mode.errors << Glaeml::Error.new(term.line, "<< Macro backtrace : #{term.macro.name}")
|
170
|
+
end
|
171
|
+
|
63
172
|
else
|
64
173
|
term.if_conds.each{ |if_cond|
|
65
174
|
|
@@ -81,8 +190,8 @@ module Glaemscribe
|
|
81
190
|
|
82
191
|
def finalize_rule(line, match_exp, replacement_exp, cross_schema = nil)
|
83
192
|
|
84
|
-
match = apply_vars(line, match_exp)
|
85
|
-
replacement = apply_vars(line, replacement_exp)
|
193
|
+
match = apply_vars(line, match_exp, true)
|
194
|
+
replacement = apply_vars(line, replacement_exp, false)
|
86
195
|
|
87
196
|
return if !match || !replacement # Failed
|
88
197
|
|
@@ -102,20 +211,42 @@ module Glaemscribe
|
|
102
211
|
|
103
212
|
var_name = $1
|
104
213
|
var_value_ex = $2
|
105
|
-
var_value = apply_vars(code_line.line, var_value_ex)
|
214
|
+
var_value = apply_vars(code_line.line, var_value_ex, true)
|
106
215
|
|
107
216
|
if !var_value
|
108
217
|
@mode.errors << Glaeml::Error.new(code_line.line, "Thus, variable {#{var_name}} could not be declared.")
|
109
218
|
return
|
110
219
|
end
|
111
220
|
|
112
|
-
add_var(var_name,var_value)
|
221
|
+
add_var(var_name, var_value, false)
|
113
222
|
|
223
|
+
elsif code_line.expression =~ POINTER_VAR_DECL_REGEXP
|
224
|
+
|
225
|
+
var_name = $1
|
226
|
+
var_value_ex = $2
|
227
|
+
|
228
|
+
add_var(var_name, var_value_ex, true)
|
229
|
+
|
114
230
|
elsif code_line.expression =~ CROSS_RULE_REGEXP
|
115
231
|
|
116
232
|
match = $1
|
117
233
|
cross = $2
|
118
|
-
|
234
|
+
var_name = $4
|
235
|
+
replacement = $5
|
236
|
+
|
237
|
+
if var_name
|
238
|
+
# This was a variable declaration
|
239
|
+
var_value = apply_vars(code_line.line, cross, false)
|
240
|
+
if !var_value
|
241
|
+
@mode.errors << Glaeml::Error.new(code_line.line, "Thus, variable {#{var_name}} could not be declared.")
|
242
|
+
return
|
243
|
+
end
|
244
|
+
cross = var_value
|
245
|
+
end
|
246
|
+
|
247
|
+
if cross == "identity"
|
248
|
+
cross = nil
|
249
|
+
end
|
119
250
|
|
120
251
|
finalize_rule(code_line.line, match, replacement, cross)
|
121
252
|
|
@@ -139,11 +270,24 @@ module Glaemscribe
|
|
139
270
|
@in_charset = {}
|
140
271
|
@rules = []
|
141
272
|
|
142
|
-
add_var("NULL","")
|
273
|
+
add_var("NULL","",false)
|
143
274
|
|
144
|
-
|
145
|
-
add_var("NBSP",
|
146
|
-
|
275
|
+
# Characters that are not easily entered or visible in a text editor
|
276
|
+
add_var("NBSP", "{UNI_A0}", false)
|
277
|
+
add_var("WJ", "{UNI_2060}", false)
|
278
|
+
add_var("ZWSP", "{UNI_200B}", false)
|
279
|
+
add_var("ZWNJ", "{UNI_200C}", false)
|
280
|
+
|
281
|
+
# The following characters are used by the mode syntax.
|
282
|
+
# Redefine some convenient tools.
|
283
|
+
add_var("UNDERSCORE", "{UNI_5F}", false)
|
284
|
+
add_var("ASTERISK", "{UNI_2A}", false)
|
285
|
+
add_var("COMMA", "{UNI_2C}", false)
|
286
|
+
add_var("LPAREN", "{UNI_28}", false)
|
287
|
+
add_var("RPAREN", "{UNI_29}", false)
|
288
|
+
add_var("LBRACKET", "{UNI_5B}", false)
|
289
|
+
add_var("RBRACKET", "{UNI_5D}", false)
|
290
|
+
|
147
291
|
descend_if_tree(@root_code_block, trans_options)
|
148
292
|
|
149
293
|
# Now that we have selected our rules, create the in_charset of the rule_group
|
@@ -151,8 +295,8 @@ module Glaemscribe
|
|
151
295
|
r.sub_rules.each { |sr|
|
152
296
|
sr.src_combination.join("").split(//).each{ |inchar|
|
153
297
|
# Add the character to the map of input characters
|
154
|
-
# Ignore '
|
155
|
-
@in_charset[inchar] = self if inchar != WORD_BREAKER && inchar !=
|
298
|
+
# Ignore '\u0000' (bounds of word) and '|' (word breaker)
|
299
|
+
@in_charset[inchar] = self if inchar != WORD_BREAKER && inchar != WORD_BOUNDARY_TREE
|
156
300
|
}
|
157
301
|
}
|
158
302
|
}
|
@@ -108,7 +108,7 @@ module Glaemscribe
|
|
108
108
|
return false
|
109
109
|
end
|
110
110
|
|
111
|
-
# Calculate all cominations for the chain
|
111
|
+
# Calculate all cominations for the chain, for the current iterator value
|
112
112
|
def combinations
|
113
113
|
resolved = []
|
114
114
|
@iterators.each_with_index{ |counter, index|
|
@@ -43,8 +43,8 @@ module Glaemscribe
|
|
43
43
|
@transcription_tree = TranscriptionTreeNode.new(nil,nil)
|
44
44
|
|
45
45
|
# Add WORD_BOUNDARY and WORD_BREAKER in the tree
|
46
|
-
@transcription_tree.add_subpath(
|
47
|
-
@transcription_tree.add_subpath(WORD_BREAKER,
|
46
|
+
@transcription_tree.add_subpath(WORD_BOUNDARY_TREE, [""])
|
47
|
+
@transcription_tree.add_subpath(WORD_BREAKER, [""])
|
48
48
|
|
49
49
|
rule_groups.each{ |rgname, rg|
|
50
50
|
rg.finalize(trans_options)
|
@@ -110,7 +110,7 @@ module Glaemscribe
|
|
110
110
|
|
111
111
|
def transcribe_word(word)
|
112
112
|
res = []
|
113
|
-
word =
|
113
|
+
word = WORD_BOUNDARY_TREE + word + WORD_BOUNDARY_TREE
|
114
114
|
while word.length != 0
|
115
115
|
r, len = @transcription_tree.transcribe(word)
|
116
116
|
word = word[len..-1]
|
data/lib/api/tts.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Glaemscribe
|
2
|
+
module API
|
3
|
+
|
4
|
+
class TTS
|
5
|
+
|
6
|
+
TTS_ENGINE_PATH = File.dirname(__FILE__) + "/../../lib_espeak/espeakng.for.glaemscribe.nowasm.sync.js"
|
7
|
+
TTS_MODULE_PATH = File.dirname(__FILE__) + "/../../lib_espeak/glaemscribe_tts.js"
|
8
|
+
|
9
|
+
def self.loaded?
|
10
|
+
!@context.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.load_engine
|
14
|
+
return if @context
|
15
|
+
|
16
|
+
@context = ::MiniRacer::Context.new
|
17
|
+
|
18
|
+
@context.attach 'console.log', proc{|o| puts o}
|
19
|
+
@context.attach 'print', proc{|o| puts o}
|
20
|
+
|
21
|
+
espeak_lib = File.open(TTS_ENGINE_PATH,"rb").read
|
22
|
+
@context.eval(espeak_lib)
|
23
|
+
|
24
|
+
tts_module = File.open(TTS_MODULE_PATH,"rb").read
|
25
|
+
@context.eval(tts_module)
|
26
|
+
|
27
|
+
@voice_list = @context.eval("Glaemscribe.TTS.voice_list()")
|
28
|
+
# puts "TTS Engine loaded."
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.voice_list
|
32
|
+
load_engine if !@context
|
33
|
+
@voice_list
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.ipa(text, voice, has_raw_mode)
|
37
|
+
load_engine if !@context
|
38
|
+
@context.eval("var esp = new Glaemscribe.TTS(); esp.synthesize_ipa(#{text.inspect},{voice:'#{voice}', has_raw_mode: #{has_raw_mode}})")
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.wav(text, voice, has_raw_mode)
|
42
|
+
load_engine if !@context
|
43
|
+
@context.eval("var esp = new Glaemscribe.TTS(); esp.synthesize_wav(#{text.inspect},{voice:'#{voice}', has_raw_mode: #{has_raw_mode}})")
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.option_name_to_voice(option_name)
|
47
|
+
option_name.downcase.gsub(/^espeak_voice_/,'').gsub('_','-')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|