ruby_speech 2.1.0-java
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.
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +17 -0
- data/CHANGELOG.md +144 -0
- data/Gemfile +3 -0
- data/Guardfile +9 -0
- data/LICENSE.md +20 -0
- data/README.md +314 -0
- data/Rakefile +34 -0
- data/assets/grammar-core.xsd +317 -0
- data/assets/grammar.xsd +37 -0
- data/assets/synthesis-core.xsd +445 -0
- data/assets/synthesis.xsd +63 -0
- data/assets/xml.xsd +287 -0
- data/ext/ruby_speech/RubySpeechGRXMLMatcher.java +64 -0
- data/ext/ruby_speech/RubySpeechService.java +23 -0
- data/ext/ruby_speech/extconf.rb +7 -0
- data/ext/ruby_speech/ruby_speech.c +97 -0
- data/lib/ruby_speech/generic_element.rb +169 -0
- data/lib/ruby_speech/grxml/element.rb +29 -0
- data/lib/ruby_speech/grxml/grammar.rb +189 -0
- data/lib/ruby_speech/grxml/item.rb +144 -0
- data/lib/ruby_speech/grxml/match.rb +16 -0
- data/lib/ruby_speech/grxml/matcher.rb +126 -0
- data/lib/ruby_speech/grxml/max_match.rb +6 -0
- data/lib/ruby_speech/grxml/no_match.rb +10 -0
- data/lib/ruby_speech/grxml/one_of.rb +31 -0
- data/lib/ruby_speech/grxml/potential_match.rb +10 -0
- data/lib/ruby_speech/grxml/rule.rb +73 -0
- data/lib/ruby_speech/grxml/ruleref.rb +69 -0
- data/lib/ruby_speech/grxml/tag.rb +29 -0
- data/lib/ruby_speech/grxml/token.rb +31 -0
- data/lib/ruby_speech/grxml.rb +39 -0
- data/lib/ruby_speech/nlsml/builder.rb +34 -0
- data/lib/ruby_speech/nlsml/document.rb +120 -0
- data/lib/ruby_speech/nlsml.rb +18 -0
- data/lib/ruby_speech/ruby_speech.jar +0 -0
- data/lib/ruby_speech/ssml/audio.rb +47 -0
- data/lib/ruby_speech/ssml/break.rb +62 -0
- data/lib/ruby_speech/ssml/desc.rb +24 -0
- data/lib/ruby_speech/ssml/element.rb +23 -0
- data/lib/ruby_speech/ssml/emphasis.rb +44 -0
- data/lib/ruby_speech/ssml/mark.rb +43 -0
- data/lib/ruby_speech/ssml/p.rb +25 -0
- data/lib/ruby_speech/ssml/phoneme.rb +72 -0
- data/lib/ruby_speech/ssml/prosody.rb +172 -0
- data/lib/ruby_speech/ssml/s.rb +25 -0
- data/lib/ruby_speech/ssml/say_as.rb +100 -0
- data/lib/ruby_speech/ssml/speak.rb +27 -0
- data/lib/ruby_speech/ssml/sub.rb +42 -0
- data/lib/ruby_speech/ssml/voice.rb +108 -0
- data/lib/ruby_speech/ssml.rb +39 -0
- data/lib/ruby_speech/version.rb +3 -0
- data/lib/ruby_speech/xml/language.rb +13 -0
- data/lib/ruby_speech/xml.rb +11 -0
- data/lib/ruby_speech.rb +36 -0
- data/ruby_speech.gemspec +42 -0
- data/spec/ruby_speech/grxml/grammar_spec.rb +341 -0
- data/spec/ruby_speech/grxml/item_spec.rb +192 -0
- data/spec/ruby_speech/grxml/match_spec.rb +15 -0
- data/spec/ruby_speech/grxml/matcher_spec.rb +688 -0
- data/spec/ruby_speech/grxml/max_match_spec.rb +17 -0
- data/spec/ruby_speech/grxml/no_match_spec.rb +17 -0
- data/spec/ruby_speech/grxml/one_of_spec.rb +49 -0
- data/spec/ruby_speech/grxml/potential_match_spec.rb +17 -0
- data/spec/ruby_speech/grxml/rule_spec.rb +125 -0
- data/spec/ruby_speech/grxml/ruleref_spec.rb +55 -0
- data/spec/ruby_speech/grxml/tag_spec.rb +41 -0
- data/spec/ruby_speech/grxml/token_spec.rb +62 -0
- data/spec/ruby_speech/grxml_spec.rb +339 -0
- data/spec/ruby_speech/nlsml_spec.rb +353 -0
- data/spec/ruby_speech/ssml/audio_spec.rb +121 -0
- data/spec/ruby_speech/ssml/break_spec.rb +100 -0
- data/spec/ruby_speech/ssml/desc_spec.rb +57 -0
- data/spec/ruby_speech/ssml/emphasis_spec.rb +110 -0
- data/spec/ruby_speech/ssml/mark_spec.rb +53 -0
- data/spec/ruby_speech/ssml/p_spec.rb +96 -0
- data/spec/ruby_speech/ssml/phoneme_spec.rb +65 -0
- data/spec/ruby_speech/ssml/prosody_spec.rb +309 -0
- data/spec/ruby_speech/ssml/s_spec.rb +92 -0
- data/spec/ruby_speech/ssml/say_as_spec.rb +71 -0
- data/spec/ruby_speech/ssml/speak_spec.rb +166 -0
- data/spec/ruby_speech/ssml/sub_spec.rb +57 -0
- data/spec/ruby_speech/ssml/voice_spec.rb +200 -0
- data/spec/ruby_speech/ssml_spec.rb +285 -0
- data/spec/ruby_speech_spec.rb +124 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/match_examples.rb +43 -0
- data/spec/support/matchers.rb +46 -0
- metadata +405 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module RubySpeech
|
|
4
|
+
module SSML
|
|
5
|
+
describe Voice do
|
|
6
|
+
its(:node_name) { should == 'voice' }
|
|
7
|
+
its(:name) { should be_nil }
|
|
8
|
+
|
|
9
|
+
describe "setting options in initializers" do
|
|
10
|
+
subject { Voice.new :language => 'jp', :gender => :male, :age => 25, :variant => 2, :name => "paul" }
|
|
11
|
+
|
|
12
|
+
its(:language) { should == 'jp' }
|
|
13
|
+
its(:gender) { should == :male }
|
|
14
|
+
its(:age) { should == 25 }
|
|
15
|
+
its(:variant) { should == 2 }
|
|
16
|
+
its(:name) { should == 'paul' }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'registers itself' do
|
|
20
|
+
Element.class_from_registration(:voice).should == Voice
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "from a document" do
|
|
24
|
+
let(:document) { '<voice xml:lang="jp" gender="male" age="25" variant="2" name="paul"/>' }
|
|
25
|
+
|
|
26
|
+
subject { Element.import document }
|
|
27
|
+
|
|
28
|
+
it { should be_instance_of Voice }
|
|
29
|
+
|
|
30
|
+
its(:language) { should == 'jp' }
|
|
31
|
+
its(:gender) { should == :male }
|
|
32
|
+
its(:age) { should == 25 }
|
|
33
|
+
its(:variant) { should == 2 }
|
|
34
|
+
its(:name) { should == 'paul' }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "#language" do
|
|
38
|
+
before { subject.language = 'jp' }
|
|
39
|
+
|
|
40
|
+
its(:language) { should == 'jp' }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "#gender" do
|
|
44
|
+
before { subject.gender = :male }
|
|
45
|
+
|
|
46
|
+
its(:gender) { should == :male }
|
|
47
|
+
|
|
48
|
+
it "with a valid gender" do
|
|
49
|
+
lambda { subject.gender = :male }.should_not raise_error
|
|
50
|
+
lambda { subject.gender = :female }.should_not raise_error
|
|
51
|
+
lambda { subject.gender = :neutral }.should_not raise_error
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "with an invalid gender" do
|
|
55
|
+
lambda { subject.gender = :something }.should raise_error(ArgumentError, "You must specify a valid gender (:male, :female, :neutral)")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "#age" do
|
|
60
|
+
before { subject.age = 12 }
|
|
61
|
+
|
|
62
|
+
its(:age) { should == 12 }
|
|
63
|
+
|
|
64
|
+
it "with an integer of 0" do
|
|
65
|
+
lambda { subject.age = 0 }.should_not raise_error
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "with an integer less than 0" do
|
|
69
|
+
lambda { subject.age = -1 }.should raise_error(ArgumentError, "You must specify a valid age (non-negative integer)")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "with something other than an integer" do
|
|
73
|
+
lambda { subject.age = "bah" }.should raise_error(ArgumentError, "You must specify a valid age (non-negative integer)")
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "#variant" do
|
|
78
|
+
before { subject.variant = 12 }
|
|
79
|
+
|
|
80
|
+
its(:variant) { should == 12 }
|
|
81
|
+
|
|
82
|
+
it "with an integer less than 1" do
|
|
83
|
+
lambda { subject.variant = 0 }.should raise_error(ArgumentError, "You must specify a valid variant (positive integer)")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "with something other than an integer" do
|
|
87
|
+
lambda { subject.variant = "bah" }.should raise_error(ArgumentError, "You must specify a valid variant (positive integer)")
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
describe "#name" do
|
|
92
|
+
before { subject.name = 'george' }
|
|
93
|
+
|
|
94
|
+
its(:name) { should == 'george' }
|
|
95
|
+
|
|
96
|
+
context "with an array of names" do
|
|
97
|
+
before { subject.name = %w{george frank} }
|
|
98
|
+
|
|
99
|
+
its(:name) { should == %w{george frank} }
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
describe "comparing objects" do
|
|
104
|
+
it "should be equal if the content, language, gender, age, variant, name are the same" do
|
|
105
|
+
Voice.new(:language => 'jp', :gender => :male, :age => 25, :variant => 2, :name => "paul", :content => "hello").should == Voice.new(:language => 'jp', :gender => :male, :age => 25, :variant => 2, :name => "paul", :content => "hello")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
describe "when the content is different" do
|
|
109
|
+
it "should not be equal" do
|
|
110
|
+
Voice.new(:content => "Hello").should_not == Voice.new(:content => "Hello there")
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
describe "when the language is different" do
|
|
115
|
+
it "should not be equal" do
|
|
116
|
+
Voice.new(:language => "Hello").should_not == Voice.new(:language => "Hello there")
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
describe "when the gender is different" do
|
|
121
|
+
it "should not be equal" do
|
|
122
|
+
Voice.new(:gender => :male).should_not == Voice.new(:gender => :female)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
describe "when the age is different" do
|
|
127
|
+
it "should not be equal" do
|
|
128
|
+
Voice.new(:age => 20).should_not == Voice.new(:age => 30)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
describe "when the variant is different" do
|
|
133
|
+
it "should not be equal" do
|
|
134
|
+
Voice.new(:variant => 1).should_not == Voice.new(:variant => 2)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
describe "when the name is different" do
|
|
139
|
+
it "should not be equal" do
|
|
140
|
+
Voice.new(:name => "Hello").should_not == Voice.new(:name => "Hello there")
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe "<<" do
|
|
146
|
+
it "should accept String" do
|
|
147
|
+
lambda { subject << 'anything' }.should_not raise_error
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "should accept Audio" do
|
|
151
|
+
lambda { subject << Audio.new }.should_not raise_error
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "should accept Break" do
|
|
155
|
+
lambda { subject << Break.new }.should_not raise_error
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "should accept Emphasis" do
|
|
159
|
+
lambda { subject << Emphasis.new }.should_not raise_error
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "should accept Mark" do
|
|
163
|
+
lambda { subject << Mark.new }.should_not raise_error
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "should accept P" do
|
|
167
|
+
lambda { subject << P.new }.should_not raise_error
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "should accept Phoneme" do
|
|
171
|
+
lambda { subject << Phoneme.new }.should_not raise_error
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "should accept Prosody" do
|
|
175
|
+
lambda { subject << Prosody.new }.should_not raise_error
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "should accept SayAs" do
|
|
179
|
+
lambda { subject << SayAs.new(:interpret_as => :foo) }.should_not raise_error
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "should accept Sub" do
|
|
183
|
+
lambda { subject << Sub.new }.should_not raise_error
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "should accept S" do
|
|
187
|
+
lambda { subject << S.new }.should_not raise_error
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "should accept Voice" do
|
|
191
|
+
lambda { subject << Voice.new }.should_not raise_error
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it "should raise InvalidChildError with non-acceptable objects" do
|
|
195
|
+
lambda { subject << 1 }.should raise_error(InvalidChildError, "A Voice can only accept String, Audio, Break, Emphasis, Mark, P, Phoneme, Prosody, SayAs, Sub, S, Voice as children")
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end # Voice
|
|
199
|
+
end # SSML
|
|
200
|
+
end # RubySpeech
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module RubySpeech
|
|
4
|
+
describe SSML do
|
|
5
|
+
describe "#draw" do
|
|
6
|
+
it "should create an SSML document" do
|
|
7
|
+
expected_doc = SSML::Speak.new
|
|
8
|
+
SSML.draw.should == expected_doc
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "can draw with a language" do
|
|
12
|
+
expected_doc = SSML::Speak.new language: 'pt-BR'
|
|
13
|
+
SSML.draw(language: 'pt-BR').should == expected_doc
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "when the return value of the block is a string" do
|
|
17
|
+
it "should be inserted into the document" do
|
|
18
|
+
expected_doc = SSML::Speak.new(:content => "Hi, I'm Fred")
|
|
19
|
+
SSML.draw { "Hi, I'm Fred" }.should == expected_doc
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "when the return value of the block is not a string" do
|
|
24
|
+
it "should not be inserted into the document" do
|
|
25
|
+
expected_doc = SSML::Speak.new
|
|
26
|
+
SSML.draw { :foo }.should == expected_doc
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe "when inserting a string" do
|
|
31
|
+
it "should work" do
|
|
32
|
+
expected_doc = SSML::Speak.new(:content => "Hi, I'm Fred")
|
|
33
|
+
SSML.draw { string "Hi, I'm Fred" }.should == expected_doc
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should allow other SSML elements to be inserted in the document" do
|
|
38
|
+
doc = SSML.draw { voice :gender => :male, :name => 'fred' }
|
|
39
|
+
expected_doc = SSML::Speak.new
|
|
40
|
+
expected_doc << SSML::Voice.new(:gender => :male, :name => 'fred')
|
|
41
|
+
doc.should == expected_doc
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should allow nested block return values" do
|
|
45
|
+
doc = RubySpeech::SSML.draw do
|
|
46
|
+
voice :gender => :male, :name => 'fred' do
|
|
47
|
+
"Hi, I'm Fred."
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
expected_doc = SSML::Speak.new
|
|
51
|
+
expected_doc << SSML::Voice.new(:gender => :male, :name => 'fred', :content => "Hi, I'm Fred.")
|
|
52
|
+
doc.should == expected_doc
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should allow nested SSML elements" do
|
|
56
|
+
doc = RubySpeech::SSML.draw do
|
|
57
|
+
voice :gender => :male, :name => 'fred' do
|
|
58
|
+
string "Hi, I'm Fred. The time is currently "
|
|
59
|
+
say_as :interpret_as => 'date', :format => 'dmy' do
|
|
60
|
+
"01/02/1960"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
voice = SSML::Voice.new(:gender => :male, :name => 'fred', :content => "Hi, I'm Fred. The time is currently ")
|
|
65
|
+
voice << SSML::SayAs.new(:interpret_as => 'date', :format => 'dmy', :content => "01/02/1960")
|
|
66
|
+
expected_doc = SSML::Speak.new
|
|
67
|
+
expected_doc << voice
|
|
68
|
+
doc.should == expected_doc
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "should allow accessing methods defined outside the block" do
|
|
72
|
+
def foo
|
|
73
|
+
'bar'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
doc = SSML.draw do
|
|
77
|
+
string foo
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
expected_doc = SSML::Speak.new :content => foo
|
|
81
|
+
doc.should == expected_doc
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe "embedding" do
|
|
85
|
+
it "SSML documents" do
|
|
86
|
+
doc1 = RubySpeech::SSML.draw do
|
|
87
|
+
string "Hi, I'm Fred. The time is currently "
|
|
88
|
+
say_as :interpret_as => 'date', :format => 'dmy' do
|
|
89
|
+
"01/02/1960"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
doc2 = RubySpeech::SSML.draw do
|
|
94
|
+
voice :gender => :male, :name => 'fred' do
|
|
95
|
+
embed doc1
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
expected_doc = RubySpeech::SSML.draw do
|
|
100
|
+
voice :gender => :male, :name => 'fred' do
|
|
101
|
+
string "Hi, I'm Fred. The time is currently "
|
|
102
|
+
say_as :interpret_as => 'date', :format => 'dmy' do
|
|
103
|
+
"01/02/1960"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
doc2.should == expected_doc
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "SSML elements" do
|
|
112
|
+
element = SSML::Emphasis.new(:content => "HELLO?")
|
|
113
|
+
|
|
114
|
+
doc = RubySpeech::SSML.draw do
|
|
115
|
+
voice :gender => :male, :name => 'fred' do
|
|
116
|
+
embed element
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
expected_doc = RubySpeech::SSML.draw do
|
|
121
|
+
voice :gender => :male, :name => 'fred' do
|
|
122
|
+
emphasis do
|
|
123
|
+
"HELLO?"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
doc.should == expected_doc
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "strings" do
|
|
132
|
+
string = "How now, brown cow?"
|
|
133
|
+
|
|
134
|
+
doc = RubySpeech::SSML.draw do
|
|
135
|
+
voice :gender => :male, :name => 'fred' do
|
|
136
|
+
embed string
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
expected_doc = RubySpeech::SSML.draw do
|
|
141
|
+
voice :gender => :male, :name => 'fred' do
|
|
142
|
+
string "How now, brown cow?"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
doc.should == expected_doc
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "should properly escape string input" do
|
|
151
|
+
doc = RubySpeech::SSML.draw do
|
|
152
|
+
voice { string "I <3 nachos." }
|
|
153
|
+
voice { "I <3 nachos." }
|
|
154
|
+
end
|
|
155
|
+
expected_doc = SSML::Speak.new
|
|
156
|
+
2.times do
|
|
157
|
+
expected_doc << SSML::Voice.new(:native_content => "I <3 nachos.")
|
|
158
|
+
end
|
|
159
|
+
doc.should == expected_doc
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "should allow all permutations of possible nested SSML elements" do
|
|
163
|
+
doc = RubySpeech::SSML.draw do
|
|
164
|
+
string "Hello world."
|
|
165
|
+
ssml_break
|
|
166
|
+
audio :src => "hello" do
|
|
167
|
+
string "HELLO?"
|
|
168
|
+
ssml_break
|
|
169
|
+
audio :src => "hello"
|
|
170
|
+
emphasis
|
|
171
|
+
prosody
|
|
172
|
+
say_as :interpret_as => 'date'
|
|
173
|
+
voice
|
|
174
|
+
end
|
|
175
|
+
emphasis do
|
|
176
|
+
string "HELLO?"
|
|
177
|
+
ssml_break
|
|
178
|
+
audio :src => "hello"
|
|
179
|
+
emphasis
|
|
180
|
+
prosody
|
|
181
|
+
say_as :interpret_as => 'date'
|
|
182
|
+
voice
|
|
183
|
+
end
|
|
184
|
+
prosody :rate => :slow do
|
|
185
|
+
string "H...E...L...L...O?"
|
|
186
|
+
ssml_break
|
|
187
|
+
audio :src => "hello"
|
|
188
|
+
emphasis
|
|
189
|
+
prosody
|
|
190
|
+
say_as :interpret_as => 'date'
|
|
191
|
+
voice
|
|
192
|
+
end
|
|
193
|
+
say_as :interpret_as => 'date', :format => 'dmy' do
|
|
194
|
+
"01/02/1960"
|
|
195
|
+
end
|
|
196
|
+
voice :gender => :male, :name => 'fred' do
|
|
197
|
+
string "Hi, I'm Fred. The time is currently "
|
|
198
|
+
say_as :interpret_as => 'date', :format => 'dmy' do
|
|
199
|
+
"01/02/1960"
|
|
200
|
+
end
|
|
201
|
+
ssml_break
|
|
202
|
+
audio :src => "hello"
|
|
203
|
+
emphasis do
|
|
204
|
+
"I'm so old"
|
|
205
|
+
end
|
|
206
|
+
prosody :rate => :fast do
|
|
207
|
+
"And yet so spritely!"
|
|
208
|
+
end
|
|
209
|
+
voice :age => 12 do
|
|
210
|
+
"And I'm young Fred"
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
expected_doc = SSML::Speak.new(:content => "Hello world.")
|
|
215
|
+
expected_doc << SSML::Break.new
|
|
216
|
+
audio = SSML::Audio.new(:src => "hello", :content => "HELLO?")
|
|
217
|
+
audio << SSML::Break.new
|
|
218
|
+
audio << SSML::Audio.new(:src => "hello")
|
|
219
|
+
audio << SSML::Emphasis.new
|
|
220
|
+
audio << SSML::Prosody.new
|
|
221
|
+
audio << SSML::SayAs.new(:interpret_as => 'date')
|
|
222
|
+
audio << SSML::Voice.new
|
|
223
|
+
expected_doc << audio
|
|
224
|
+
emphasis = SSML::Emphasis.new(:content => "HELLO?")
|
|
225
|
+
emphasis << SSML::Break.new
|
|
226
|
+
emphasis << SSML::Audio.new(:src => "hello")
|
|
227
|
+
emphasis << SSML::Emphasis.new
|
|
228
|
+
emphasis << SSML::Prosody.new
|
|
229
|
+
emphasis << SSML::SayAs.new(:interpret_as => 'date')
|
|
230
|
+
emphasis << SSML::Voice.new
|
|
231
|
+
expected_doc << emphasis
|
|
232
|
+
prosody = SSML::Prosody.new(:rate => :slow, :content => "H...E...L...L...O?")
|
|
233
|
+
prosody << SSML::Break.new
|
|
234
|
+
prosody << SSML::Audio.new(:src => "hello")
|
|
235
|
+
prosody << SSML::Emphasis.new
|
|
236
|
+
prosody << SSML::Prosody.new
|
|
237
|
+
prosody << SSML::SayAs.new(:interpret_as => 'date')
|
|
238
|
+
prosody << SSML::Voice.new
|
|
239
|
+
expected_doc << prosody
|
|
240
|
+
expected_doc << SSML::SayAs.new(:interpret_as => 'date', :format => 'dmy', :content => "01/02/1960")
|
|
241
|
+
voice = SSML::Voice.new(:gender => :male, :name => 'fred', :content => "Hi, I'm Fred. The time is currently ")
|
|
242
|
+
voice << SSML::SayAs.new(:interpret_as => 'date', :format => 'dmy', :content => "01/02/1960")
|
|
243
|
+
voice << SSML::Break.new
|
|
244
|
+
voice << SSML::Audio.new(:src => "hello")
|
|
245
|
+
voice << SSML::Emphasis.new(:content => "I'm so old")
|
|
246
|
+
voice << SSML::Prosody.new(:rate => :fast, :content => "And yet so spritely!")
|
|
247
|
+
voice << SSML::Voice.new(:age => 12, :content => "And I'm young Fred")
|
|
248
|
+
expected_doc << voice
|
|
249
|
+
doc.should == expected_doc
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
describe "importing nested tags" do
|
|
254
|
+
let(:say_as) { SSML::SayAs.new :interpret_as => 'date', :format => 'dmy', :content => "01/02/1960" }
|
|
255
|
+
let(:string) { "Hi, I'm Fred. The time is currently " }
|
|
256
|
+
let :voice do
|
|
257
|
+
SSML::Voice.new(:gender => :male, :name => 'fred', :content => string).tap do |voice|
|
|
258
|
+
voice << say_as
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
let :document do
|
|
263
|
+
SSML::Speak.new.tap { |doc| doc << voice }.to_s
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
let(:import) { SSML.import document }
|
|
267
|
+
|
|
268
|
+
subject { import }
|
|
269
|
+
|
|
270
|
+
it "should work" do
|
|
271
|
+
lambda { subject }.should_not raise_error
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it { should be_a SSML::Speak }
|
|
275
|
+
|
|
276
|
+
its(:children) { should == [voice] }
|
|
277
|
+
|
|
278
|
+
describe "voice" do
|
|
279
|
+
subject { import.children.first }
|
|
280
|
+
|
|
281
|
+
its(:children) { should == [string, say_as] }
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RubySpeech do
|
|
4
|
+
describe ".parse" do
|
|
5
|
+
subject do
|
|
6
|
+
RubySpeech.parse example_document
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context "with an SSML document" do
|
|
10
|
+
let :example_document do
|
|
11
|
+
'''<?xml version="1.0"?>
|
|
12
|
+
<!DOCTYPE speak PUBLIC "-//W3C//DTD SYNTHESIS 1.0//EN"
|
|
13
|
+
"http://www.w3.org/TR/speech-synthesis/synthesis.dtd">
|
|
14
|
+
<speak version="1.0"
|
|
15
|
+
xmlns="http://www.w3.org/2001/10/synthesis"
|
|
16
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
17
|
+
xsi:schemaLocation="http://www.w3.org/2001/10/synthesis
|
|
18
|
+
http://www.w3.org/TR/speech-synthesis/synthesis.xsd"
|
|
19
|
+
xml:lang="en-US">
|
|
20
|
+
<p>
|
|
21
|
+
<s>You have 4 new messages.</s>
|
|
22
|
+
<s>The first is from Stephanie Williams and arrived at <break/> 3:45pm.
|
|
23
|
+
</s>
|
|
24
|
+
<s>
|
|
25
|
+
The subject is <prosody rate="-20%">ski trip</prosody>
|
|
26
|
+
</s>
|
|
27
|
+
|
|
28
|
+
</p>
|
|
29
|
+
</speak>
|
|
30
|
+
'''
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it { should be_a RubySpeech::SSML::Element }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context "with a GRXML document" do
|
|
37
|
+
let :example_document do
|
|
38
|
+
'''<?xml version="1.0" encoding="UTF-8"?>
|
|
39
|
+
|
|
40
|
+
<!DOCTYPE grammar PUBLIC "-//W3C//DTD GRAMMAR 1.0//EN"
|
|
41
|
+
"http://www.w3.org/TR/speech-grammar/grammar.dtd">
|
|
42
|
+
|
|
43
|
+
<grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en"
|
|
44
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
45
|
+
xsi:schemaLocation="http://www.w3.org/2001/06/grammar
|
|
46
|
+
http://www.w3.org/TR/speech-grammar/grammar.xsd"
|
|
47
|
+
version="1.0" mode="voice" root="basicCmd">
|
|
48
|
+
|
|
49
|
+
<meta name="author" content="Stephanie Williams"/>
|
|
50
|
+
|
|
51
|
+
<rule id="basicCmd" scope="public">
|
|
52
|
+
<example> please move the window </example>
|
|
53
|
+
<example> open a file </example>
|
|
54
|
+
|
|
55
|
+
<ruleref uri="http://grammar.example.com/politeness.grxml#startPolite"/>
|
|
56
|
+
|
|
57
|
+
<ruleref uri="#command"/>
|
|
58
|
+
<ruleref uri="http://grammar.example.com/politeness.grxml#endPolite"/>
|
|
59
|
+
|
|
60
|
+
</rule>
|
|
61
|
+
|
|
62
|
+
<rule id="command">
|
|
63
|
+
<ruleref uri="#action"/> <ruleref uri="#object"/>
|
|
64
|
+
</rule>
|
|
65
|
+
|
|
66
|
+
<rule id="action">
|
|
67
|
+
<one-of>
|
|
68
|
+
<item weight="10"> open <tag>TAG-CONTENT-1</tag> </item>
|
|
69
|
+
<item weight="2"> close <tag>TAG-CONTENT-2</tag> </item>
|
|
70
|
+
<item weight="1"> delete <tag>TAG-CONTENT-3</tag> </item>
|
|
71
|
+
<item weight="1"> move <tag>TAG-CONTENT-4</tag> </item>
|
|
72
|
+
</one-of>
|
|
73
|
+
</rule>
|
|
74
|
+
|
|
75
|
+
<rule id="object">
|
|
76
|
+
<item repeat="0-1">
|
|
77
|
+
<one-of>
|
|
78
|
+
<item> the </item>
|
|
79
|
+
<item> a </item>
|
|
80
|
+
</one-of>
|
|
81
|
+
</item>
|
|
82
|
+
|
|
83
|
+
<one-of>
|
|
84
|
+
<item> window </item>
|
|
85
|
+
<item> file </item>
|
|
86
|
+
<item> menu </item>
|
|
87
|
+
</one-of>
|
|
88
|
+
</rule>
|
|
89
|
+
|
|
90
|
+
</grammar>
|
|
91
|
+
'''
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it { should be_a RubySpeech::GRXML::Element }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context "with an NLSML document" do
|
|
98
|
+
let :example_document do
|
|
99
|
+
'''
|
|
100
|
+
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://flight">
|
|
101
|
+
<interpretation confidence="60">
|
|
102
|
+
<input mode="speech">I want to go to Pittsburgh</input>
|
|
103
|
+
<instance>
|
|
104
|
+
<airline>
|
|
105
|
+
<to_city>Pittsburgh</to_city>
|
|
106
|
+
</airline>
|
|
107
|
+
</instance>
|
|
108
|
+
</interpretation>
|
|
109
|
+
<interpretation confidence="40">
|
|
110
|
+
<input>I want to go to Stockholm</input>
|
|
111
|
+
<instance>
|
|
112
|
+
<airline>
|
|
113
|
+
<to_city>Stockholm</to_city>
|
|
114
|
+
</airline>
|
|
115
|
+
</instance>
|
|
116
|
+
</interpretation>
|
|
117
|
+
</result>
|
|
118
|
+
'''
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it { should be_a RubySpeech::NLSML::Document }
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'ruby_speech'
|
|
2
|
+
|
|
3
|
+
include RubySpeech::GRXML
|
|
4
|
+
include RubySpeech::XML::Language
|
|
5
|
+
|
|
6
|
+
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
|
|
7
|
+
|
|
8
|
+
schema_file_path = File.expand_path File.join(__FILE__, '../../assets/synthesis.xsd')
|
|
9
|
+
puts "Loading the SSML Schema from #{schema_file_path}..."
|
|
10
|
+
SSML_SCHEMA = Nokogiri::XML::Schema File.open(schema_file_path)
|
|
11
|
+
puts "Finished loading schema."
|
|
12
|
+
|
|
13
|
+
schema_file_path = File.expand_path File.join(__FILE__, '../../assets/grammar.xsd')
|
|
14
|
+
puts "Loading the GRXML Schema from #{schema_file_path}..."
|
|
15
|
+
GRXML_SCHEMA = Nokogiri::XML::Schema File.open(schema_file_path)
|
|
16
|
+
puts "Finished loading schema."
|
|
17
|
+
|
|
18
|
+
RSpec.configure do |config|
|
|
19
|
+
config.filter_run :focus => true
|
|
20
|
+
config.run_all_when_everything_filtered = true
|
|
21
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
shared_examples_for "match" do
|
|
2
|
+
subject do
|
|
3
|
+
described_class.new :mode => :dtmf,
|
|
4
|
+
:confidence => 1,
|
|
5
|
+
:utterance => '6',
|
|
6
|
+
:interpretation => 'foo'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
its(:mode) { should == :dtmf }
|
|
10
|
+
its(:confidence) { should == 1 }
|
|
11
|
+
its(:utterance) { should == '6' }
|
|
12
|
+
its(:interpretation) { should == 'foo' }
|
|
13
|
+
|
|
14
|
+
describe "equality" do
|
|
15
|
+
it "should be equal when mode, confidence, utterance and interpretation are the same" do
|
|
16
|
+
described_class.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo').should == described_class.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "when the mode is different" do
|
|
20
|
+
it "should not be equal" do
|
|
21
|
+
described_class.new(:mode => :dtmf).should_not == described_class.new(:mode => :speech)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe "when the confidence is different" do
|
|
26
|
+
it "should not be equal" do
|
|
27
|
+
described_class.new(:confidence => 1).should_not == described_class.new(:confidence => 0)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe "when the utterance is different" do
|
|
32
|
+
it "should not be equal" do
|
|
33
|
+
described_class.new(:utterance => '6').should_not == described_class.new(:utterance => 'foo')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "when the interpretation is different" do
|
|
38
|
+
it "should not be equal" do
|
|
39
|
+
described_class.new(:interpretation => 'foo').should_not == described_class.new(:interpretation => 'bar')
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|