glaemscribe 1.1.14 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|