ruby_speech 2.1.2 → 2.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 +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
|