ruby_speech 2.1.2 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/CHANGELOG.md +8 -0
- data/README.md +23 -0
- data/ext/ruby_speech/extconf.rb +3 -1
- data/ext/ruby_speech/ruby_speech.c +4 -1
- data/lib/ruby_speech.rb +6 -19
- data/lib/ruby_speech/generic_element.rb +141 -29
- data/lib/ruby_speech/grxml.rb +16 -22
- data/lib/ruby_speech/grxml/element.rb +6 -6
- data/lib/ruby_speech/grxml/grammar.rb +29 -12
- data/lib/ruby_speech/grxml/item.rb +13 -0
- data/lib/ruby_speech/grxml/matcher.rb +5 -1
- data/lib/ruby_speech/grxml/one_of.rb +4 -0
- data/lib/ruby_speech/grxml/rule.rb +10 -0
- data/lib/ruby_speech/grxml/token.rb +3 -0
- data/lib/ruby_speech/nlsml.rb +3 -9
- data/lib/ruby_speech/ssml.rb +20 -22
- data/lib/ruby_speech/ssml/audio.rb +17 -0
- data/lib/ruby_speech/ssml/desc.rb +4 -0
- data/lib/ruby_speech/ssml/element.rb +5 -3
- data/lib/ruby_speech/ssml/emphasis.rb +17 -0
- data/lib/ruby_speech/ssml/mark.rb +2 -0
- data/lib/ruby_speech/ssml/p.rb +21 -0
- data/lib/ruby_speech/ssml/phoneme.rb +2 -0
- data/lib/ruby_speech/ssml/prosody.rb +15 -0
- data/lib/ruby_speech/ssml/s.rb +20 -0
- data/lib/ruby_speech/ssml/say_as.rb +2 -0
- data/lib/ruby_speech/ssml/speak.rb +19 -1
- data/lib/ruby_speech/ssml/sub.rb +2 -0
- data/lib/ruby_speech/ssml/voice.rb +19 -0
- data/lib/ruby_speech/version.rb +1 -1
- data/ruby_speech.gemspec +2 -3
- data/spec/ruby_speech/grxml/grammar_spec.rb +35 -30
- data/spec/ruby_speech/grxml/item_spec.rb +8 -6
- data/spec/ruby_speech/grxml/one_of_spec.rb +7 -3
- data/spec/ruby_speech/grxml/rule_spec.rb +14 -12
- data/spec/ruby_speech/grxml/ruleref_spec.rb +5 -3
- data/spec/ruby_speech/grxml/tag_spec.rb +6 -2
- data/spec/ruby_speech/grxml/token_spec.rb +6 -2
- data/spec/ruby_speech/grxml_spec.rb +57 -69
- data/spec/ruby_speech/ssml/audio_spec.rb +20 -16
- data/spec/ruby_speech/ssml/break_spec.rb +14 -10
- data/spec/ruby_speech/ssml/desc_spec.rb +9 -5
- data/spec/ruby_speech/ssml/emphasis_spec.rb +17 -13
- data/spec/ruby_speech/ssml/mark_spec.rb +7 -3
- data/spec/ruby_speech/ssml/p_spec.rb +18 -14
- data/spec/ruby_speech/ssml/phoneme_spec.rb +10 -6
- data/spec/ruby_speech/ssml/prosody_spec.rb +29 -25
- data/spec/ruby_speech/ssml/s_spec.rb +17 -13
- data/spec/ruby_speech/ssml/say_as_spec.rb +11 -7
- data/spec/ruby_speech/ssml/speak_spec.rb +48 -32
- data/spec/ruby_speech/ssml/sub_spec.rb +9 -5
- data/spec/ruby_speech/ssml/voice_spec.rb +23 -19
- data/spec/ruby_speech/ssml_spec.rb +64 -63
- data/spec/spec_helper.rb +0 -3
- metadata +10 -31
- data/lib/ruby_speech/xml.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec0d77b52aa0d3a5f6984d3a966592337bf744b8
|
4
|
+
data.tar.gz: dd2535eab8d121f262017bd29cb881021652b1ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23a82e611e67b400e6fd06560e5ae7bcec8a68df565ac6c82378dcb2d86378ac75696b5f6399f39d275c8c98ec9cc0126209b60f1b78bf262bc2b97b65f7f453
|
7
|
+
data.tar.gz: 9816cb0183ec5138a976417b27beae562590eba32d205076294855a8160f763828bfc84a548fa603e5758970cc73affe65838e84dc541c4abf3054b5bd71ee2c
|
data/.travis.yml
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
language: ruby
|
2
2
|
|
3
3
|
rvm:
|
4
|
-
- 1.9.2
|
5
4
|
- 1.9.3
|
6
5
|
- 2.0.0
|
7
6
|
- jruby-19mode
|
@@ -9,7 +8,7 @@ rvm:
|
|
9
8
|
- ruby-head
|
10
9
|
matrix:
|
11
10
|
allow_failures:
|
12
|
-
|
11
|
+
- rvm: ruby-head
|
13
12
|
before_install:
|
14
13
|
- sudo apt-get install libpcre3 libpcre3-dev
|
15
14
|
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# [develop](https://github.com/benlangfeld/ruby_speech)
|
2
2
|
|
3
|
+
# [2.2.0](https://github.com/benlangfeld/ruby_speech/compare/v2.1.2...v2.2.0) - [2013-06-26](https://rubygems.org/gems/ruby_speech/versions/2.2.0)
|
4
|
+
* Bugfix: Constant autoload in rbx C extensions doesn't work properly
|
5
|
+
* Bugfix: No longer subclass or copy nodes, use delegation instead
|
6
|
+
* Bugfix: Java 1.6 compatability
|
7
|
+
* CS: Remove niceogiri dependency
|
8
|
+
* CS: Remove autoloading
|
9
|
+
* CS: Depend on activesupport less
|
10
|
+
|
3
11
|
# [2.1.2](https://github.com/benlangfeld/ruby_speech/compare/v2.1.1...v2.1.2) - [2013-06-05](https://rubygems.org/gems/ruby_speech/versions/2.1.2)
|
4
12
|
* Bugfix: Allow wrapping a pre-parsed XML node nested arbitrary deeply as an NLSML document
|
5
13
|
|
data/README.md
CHANGED
@@ -1,9 +1,32 @@
|
|
1
1
|
# RubySpeech
|
2
2
|
RubySpeech is a library for constructing and parsing Text to Speech (TTS) and Automatic Speech Recognition (ASR) documents such as [SSML](http://www.w3.org/TR/speech-synthesis), [GRXML](http://www.w3.org/TR/speech-grammar/) and [NLSML](http://www.w3.org/TR/nl-spec/). Such documents can be constructed to be processed by TTS and ASR engines, parsed as the result from such, or used in the implementation of such engines.
|
3
3
|
|
4
|
+
## Dependencies
|
5
|
+
|
6
|
+
### pcre (except on JRuby)
|
7
|
+
|
8
|
+
#### On OSX with Homebrew
|
9
|
+
```
|
10
|
+
brew install pcre
|
11
|
+
```
|
12
|
+
|
13
|
+
#### On Ubuntu/Debian
|
14
|
+
```
|
15
|
+
sudo apt-get install libpcre3 libpcre3-dev
|
16
|
+
```
|
17
|
+
|
18
|
+
#### On CentOS
|
19
|
+
```
|
20
|
+
sudo yum install pcre-devel
|
21
|
+
```
|
22
|
+
|
4
23
|
## Installation
|
5
24
|
gem install ruby_speech
|
6
25
|
|
26
|
+
## Ruby Version Compatability
|
27
|
+
* CRuby 1.9.3+ (1.9.2 is unofficially supported, but not regularly tested)
|
28
|
+
* JRuby 1.7+
|
29
|
+
|
7
30
|
## Library
|
8
31
|
|
9
32
|
### SSML
|
data/ext/ruby_speech/extconf.rb
CHANGED
@@ -2,6 +2,8 @@ require 'mkmf'
|
|
2
2
|
|
3
3
|
$LIBS << " -lpcre"
|
4
4
|
|
5
|
-
|
5
|
+
unless find_header('pcre.h')
|
6
|
+
abort "-----\nPCRE is missing. You must install it as per the README @ https://github.com/benlangfeld/ruby_speech\n-----"
|
7
|
+
end
|
6
8
|
|
7
9
|
create_makefile 'ruby_speech/ruby_speech'
|
@@ -33,12 +33,15 @@ static int is_match_end(pcre *compiled_regex, const char *input)
|
|
33
33
|
char search_input[MAX_INPUT_SIZE + 2];
|
34
34
|
const char *search_set = "0123456789#*ABCD";
|
35
35
|
const char *search = strchr(search_set, input[input_size - 1]); /* start with last digit in input */
|
36
|
+
int i;
|
36
37
|
|
37
38
|
/* For each digit in search_set, check if input + search_set digit is a potential match.
|
38
39
|
If so, then this is not a match end.
|
39
40
|
*/
|
41
|
+
if (strlen(input) > MAX_INPUT_SIZE) {
|
42
|
+
return 0;
|
43
|
+
}
|
40
44
|
sprintf(search_input, "%sZ", input);
|
41
|
-
int i;
|
42
45
|
for (i = 0; i < 16; i++) {
|
43
46
|
int result;
|
44
47
|
if (!*search) {
|
data/lib/ruby_speech.rb
CHANGED
@@ -1,24 +1,13 @@
|
|
1
1
|
%w{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
nokogiri
|
3
|
+
|
4
|
+
ruby_speech/version
|
5
|
+
ruby_speech/ssml
|
6
|
+
ruby_speech/grxml
|
7
|
+
ruby_speech/nlsml
|
7
8
|
}.each { |f| require f }
|
8
9
|
|
9
10
|
module RubySpeech
|
10
|
-
extend ActiveSupport::Autoload
|
11
|
-
|
12
|
-
autoload :Version
|
13
|
-
|
14
|
-
eager_autoload do
|
15
|
-
autoload :GenericElement
|
16
|
-
autoload :SSML
|
17
|
-
autoload :GRXML
|
18
|
-
autoload :NLSML
|
19
|
-
autoload :XML
|
20
|
-
end
|
21
|
-
|
22
11
|
def self.parse(string)
|
23
12
|
document = Nokogiri::XML.parse string, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS
|
24
13
|
namespace = document.root.namespace
|
@@ -32,5 +21,3 @@ module RubySpeech
|
|
32
21
|
end
|
33
22
|
end
|
34
23
|
end
|
35
|
-
|
36
|
-
ActiveSupport::Autoload.eager_autoload!
|
@@ -41,34 +41,42 @@ module RubySpeech
|
|
41
41
|
# @param [XML::Node] node the node to import
|
42
42
|
# @return the appropriate object based on the node name and namespace
|
43
43
|
def import(node)
|
44
|
-
node = Nokogiri::XML.parse(node, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root unless node.is_a?(Nokogiri::XML::Node)
|
44
|
+
node = Nokogiri::XML.parse(node, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root unless node.is_a?(Nokogiri::XML::Node) || node.is_a?(GenericElement)
|
45
45
|
return node.content if node.is_a?(Nokogiri::XML::Text)
|
46
46
|
klass = class_from_registration node.node_name
|
47
47
|
if klass && klass != self
|
48
48
|
klass.import node
|
49
49
|
else
|
50
|
-
new.inherit node
|
50
|
+
new(node.document).inherit node
|
51
51
|
end
|
52
52
|
end
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
block_return = new_node.eval_dsl_block &block
|
58
|
-
new_node.string block_return if block_return.is_a?(String) && block_return.present?
|
59
|
-
end
|
60
|
-
end
|
55
|
+
def initialize(doc, atts = nil, &block)
|
56
|
+
@doc = doc
|
57
|
+
build atts, &block if atts || block_given?
|
61
58
|
end
|
62
59
|
|
63
60
|
attr_writer :parent
|
64
61
|
|
62
|
+
def node
|
63
|
+
@node || create_node
|
64
|
+
end
|
65
|
+
|
65
66
|
def parent
|
66
67
|
@parent || super
|
67
68
|
end
|
68
69
|
|
69
70
|
def inherit(node)
|
70
71
|
self.parent = node.parent
|
71
|
-
|
72
|
+
@node = node
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
def build(atts, &block)
|
77
|
+
mass_assign atts
|
78
|
+
block_return = eval_dsl_block &block
|
79
|
+
string block_return if block_return.is_a?(String) && !block_return.length.zero?
|
72
80
|
end
|
73
81
|
|
74
82
|
def version
|
@@ -94,9 +102,16 @@ module RubySpeech
|
|
94
102
|
end
|
95
103
|
|
96
104
|
def +(other)
|
97
|
-
|
98
|
-
|
99
|
-
|
105
|
+
new_doc = Nokogiri::XML::Document.new
|
106
|
+
self.class.new(new_doc).tap do |new_element|
|
107
|
+
new_doc.root = new_element.node
|
108
|
+
if Nokogiri.jruby?
|
109
|
+
new_element.add_child self.nokogiri_children
|
110
|
+
new_element.add_child other.nokogiri_children
|
111
|
+
else
|
112
|
+
# TODO: This is yucky because it requires serialization
|
113
|
+
new_element.add_child self.nokogiri_children.to_xml
|
114
|
+
new_element.add_child other.nokogiri_children.to_xml
|
100
115
|
end
|
101
116
|
end
|
102
117
|
end
|
@@ -113,15 +128,30 @@ module RubySpeech
|
|
113
128
|
expression << type.to_s
|
114
129
|
|
115
130
|
expression << '[' << attributes.inject([]) do |h, (key, value)|
|
116
|
-
h << "@#{
|
131
|
+
h << "@#{key}='#{value}'"
|
117
132
|
end.join(',') << ']' if attributes
|
118
133
|
|
119
|
-
xpath expression, :ns =>
|
134
|
+
xpath expression, :ns => self.class.namespace
|
120
135
|
else
|
121
136
|
super()
|
122
137
|
end.map { |c| self.class.import c }
|
123
138
|
end
|
124
139
|
|
140
|
+
def nokogiri_children
|
141
|
+
node.children
|
142
|
+
end
|
143
|
+
|
144
|
+
def <<(other)
|
145
|
+
case other
|
146
|
+
when GenericElement
|
147
|
+
super other.node
|
148
|
+
when String
|
149
|
+
string other
|
150
|
+
else
|
151
|
+
super other
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
125
155
|
def embed(other)
|
126
156
|
case other
|
127
157
|
when String
|
@@ -141,18 +171,6 @@ module RubySpeech
|
|
141
171
|
self << Nokogiri::XML::Text.new(other, document)
|
142
172
|
end
|
143
173
|
|
144
|
-
def method_missing(method_name, *args, &block)
|
145
|
-
const_name = method_name.to_s.sub('ssml', '').titleize.gsub(' ', '')
|
146
|
-
if self.class.module.const_defined?(const_name)
|
147
|
-
const = self.class.module.const_get const_name
|
148
|
-
embed const.new(*args, &block)
|
149
|
-
elsif @block_binding && @block_binding.respond_to?(method_name)
|
150
|
-
@block_binding.send method_name, *args, &block
|
151
|
-
else
|
152
|
-
super
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
174
|
def clone
|
157
175
|
GRXML.import to_xml
|
158
176
|
end
|
@@ -162,8 +180,102 @@ module RubySpeech
|
|
162
180
|
block.call self
|
163
181
|
end
|
164
182
|
|
165
|
-
|
166
|
-
|
183
|
+
# Helper method to read an attribute
|
184
|
+
#
|
185
|
+
# @param [#to_sym] attr_name the name of the attribute
|
186
|
+
# @param [String, Symbol, nil] to_call the name of the method to call on
|
187
|
+
# the returned value
|
188
|
+
# @return nil or the value
|
189
|
+
def read_attr(attr_name, to_call = nil)
|
190
|
+
val = self[attr_name]
|
191
|
+
val && to_call ? val.__send__(to_call) : val
|
192
|
+
end
|
193
|
+
|
194
|
+
# Helper method to write a value to an attribute
|
195
|
+
#
|
196
|
+
# @param [#to_sym] attr_name the name of the attribute
|
197
|
+
# @param [#to_s] value the value to set the attribute to
|
198
|
+
def write_attr(attr_name, value, to_call = nil)
|
199
|
+
self[attr_name] = value && to_call ? value.__send__(to_call) : value
|
200
|
+
end
|
201
|
+
|
202
|
+
# Attach a namespace to the node
|
203
|
+
#
|
204
|
+
# @overload namespace=(ns)
|
205
|
+
# Attach an already created XML::Namespace
|
206
|
+
# @param [XML::Namespace] ns the namespace object
|
207
|
+
# @overload namespace=(ns)
|
208
|
+
# Create a new namespace and attach it
|
209
|
+
# @param [String] ns the namespace uri
|
210
|
+
def namespace=(namespaces)
|
211
|
+
case namespaces
|
212
|
+
when Nokogiri::XML::Namespace
|
213
|
+
super namespaces
|
214
|
+
when String
|
215
|
+
ns = self.add_namespace nil, namespaces
|
216
|
+
super ns
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Helper method to get the node's namespace
|
221
|
+
#
|
222
|
+
# @return [XML::Namespace, nil] The node's namespace object if it exists
|
223
|
+
def namespace_href
|
224
|
+
namespace.href if namespace
|
225
|
+
end
|
226
|
+
|
227
|
+
# The node as XML
|
228
|
+
#
|
229
|
+
# @return [String] XML representation of the node
|
230
|
+
def inspect
|
231
|
+
self.to_xml
|
232
|
+
end
|
233
|
+
|
234
|
+
def to_s
|
235
|
+
to_xml
|
236
|
+
end
|
237
|
+
|
238
|
+
# Check that a set of fields are equal between nodes
|
239
|
+
#
|
240
|
+
# @param [Node] other the other node to compare against
|
241
|
+
# @param [*#to_s] fields the set of fields to compare
|
242
|
+
# @return [Fixnum<-1,0,1>]
|
243
|
+
def eql?(o, *fields)
|
244
|
+
o.is_a?(self.class) && ([:content, :children] + fields).all? { |f| self.__send__(f) == o.__send__(f) }
|
245
|
+
end
|
246
|
+
|
247
|
+
# @private
|
248
|
+
def ==(o)
|
249
|
+
eql?(o)
|
250
|
+
end
|
251
|
+
|
252
|
+
def create_node
|
253
|
+
@node = Nokogiri::XML::Node.new self.class.registered_name, @doc
|
254
|
+
mass_assign self.class.defaults
|
255
|
+
@node
|
256
|
+
end
|
257
|
+
|
258
|
+
def mass_assign(attrs)
|
259
|
+
attrs.each_pair { |k, v| send :"#{k}=", v } if attrs
|
260
|
+
end
|
261
|
+
|
262
|
+
def method_missing(method_name, *args, &block)
|
263
|
+
if node.respond_to?(method_name)
|
264
|
+
return node.send method_name, *args, &block
|
265
|
+
end
|
266
|
+
|
267
|
+
const_name = method_name.to_s.sub('ssml_', '').gsub('_', '-')
|
268
|
+
if const = self.class.class_from_registration(const_name)
|
269
|
+
embed const.new(self.document, *args, &block)
|
270
|
+
elsif @block_binding && @block_binding.respond_to?(method_name)
|
271
|
+
@block_binding.send method_name, *args, &block
|
272
|
+
else
|
273
|
+
super
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def respond_to_missing?(method_name, include_private = false)
|
278
|
+
node.respond_to?(method_name, include_private) || super
|
167
279
|
end
|
168
280
|
end # Element
|
169
281
|
end # RubySpeech
|
data/lib/ruby_speech/grxml.rb
CHANGED
@@ -1,30 +1,26 @@
|
|
1
|
+
require 'ruby_speech/grxml/matcher'
|
2
|
+
require 'ruby_speech/grxml/element'
|
3
|
+
|
1
4
|
module RubySpeech
|
2
5
|
module GRXML
|
3
|
-
extend ActiveSupport::Autoload
|
4
|
-
|
5
|
-
eager_autoload do
|
6
|
-
autoload :Element
|
7
|
-
autoload :Grammar
|
8
|
-
autoload :Rule
|
9
|
-
autoload :Item
|
10
|
-
autoload :OneOf
|
11
|
-
autoload :Ruleref
|
12
|
-
autoload :Tag
|
13
|
-
autoload :Token
|
14
|
-
end
|
15
|
-
|
16
|
-
autoload :Match
|
17
|
-
autoload :Matcher
|
18
|
-
autoload :MaxMatch
|
19
|
-
autoload :NoMatch
|
20
|
-
autoload :PotentialMatch
|
21
|
-
|
22
6
|
InvalidChildError = Class.new StandardError
|
23
7
|
|
24
8
|
GRXML_NAMESPACE = 'http://www.w3.org/2001/06/grammar'
|
25
9
|
|
10
|
+
%w{
|
11
|
+
grammar
|
12
|
+
rule
|
13
|
+
item
|
14
|
+
one_of
|
15
|
+
ruleref
|
16
|
+
tag
|
17
|
+
token
|
18
|
+
}.each { |f| require "ruby_speech/grxml/#{f}" }
|
19
|
+
|
26
20
|
def self.draw(attributes = {}, &block)
|
27
|
-
|
21
|
+
document = Nokogiri::XML::Document.new
|
22
|
+
Grammar.new(document, attributes).tap do |grammar|
|
23
|
+
document.root = grammar.node
|
28
24
|
block_return = grammar.eval_dsl_block &block
|
29
25
|
grammar << block_return if block_return.is_a?(String)
|
30
26
|
end.assert_has_matching_root_rule
|
@@ -35,5 +31,3 @@ module RubySpeech
|
|
35
31
|
end
|
36
32
|
end # GRXML
|
37
33
|
end # RubySpeech
|
38
|
-
|
39
|
-
ActiveSupport::Autoload.eager_autoload!
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'ruby_speech/generic_element'
|
2
2
|
|
3
3
|
module RubySpeech
|
4
4
|
module GRXML
|
5
|
-
class Element
|
5
|
+
class Element
|
6
6
|
def self.namespace
|
7
7
|
GRXML_NAMESPACE
|
8
8
|
end
|
@@ -15,12 +15,12 @@ module RubySpeech
|
|
15
15
|
GRXML
|
16
16
|
end
|
17
17
|
|
18
|
-
alias_method :nokogiri_children, :children
|
19
|
-
|
20
|
-
alias :to_doc :document
|
21
|
-
|
22
18
|
include GenericElement
|
23
19
|
|
20
|
+
def to_doc
|
21
|
+
document
|
22
|
+
end
|
23
|
+
|
24
24
|
def regexp_content # :nodoc:
|
25
25
|
"(#{children.map(&:regexp_content).join})"
|
26
26
|
end
|