ruby_speech 2.3.2-java → 2.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ce3cb16ff3eaf366c78390c3473c6c490c08371a
4
- data.tar.gz: 389193549cb748c0da31dadaf564e1b31786c5f2
3
+ metadata.gz: 72228f3e968bcd511d58f2504272dda59b04bf83
4
+ data.tar.gz: 8570fee51e92363c6096d4aeb9a58b13d16191aa
5
5
  SHA512:
6
- metadata.gz: ff3712f5fcb287299ce97b7389c7f2be8e991116f320600014b415f4d90818c3f3e4c1d043303eac2a6e866705770b625f63aaf5c3e2364bb87eaf4cbe9be4bc
7
- data.tar.gz: 051bcf95b593cb586bad668a47c60b61ba009f05807204f978d4ae295e038eda05260307932355ff5b5b28034a7d6501153c1e974e2bb1bc3e1bf008be602799
6
+ metadata.gz: 86362dede47c17045c9f6dd40f701acdf206d2ac67e6f459a4779a3fbd2090c57bdb36eb39e3f9c1aae474ff4a6e46b0bb46f3070ba314e85b942dd4da9dc36d
7
+ data.tar.gz: 5fd3ced7cc8c94062a79ea106dac623be9e3de14f4526006c4f8cd6ab0c165b02f7c624543bffb1469ec05f7abd5118512ebf717c1767c357e525610150cdefd
@@ -1,17 +1,38 @@
1
1
  language: ruby
2
2
 
3
- rvm:
4
- - 1.9.3
5
- - 2.0.0
6
- - 2.1.0
7
- - jruby
8
- - rbx
9
- - ruby-head
10
3
  matrix:
4
+ include:
5
+ - rvm: 1.9.3
6
+ - rvm: 2.0.0
7
+ - rvm: 2.1.0
8
+ - rvm: 2.2.0
9
+ - rvm: 2.3.0
10
+ - rvm: rbx-2
11
+ - rvm: rbx-3
12
+ - rvm: ruby-head
13
+ - rvm: jruby-1.7
14
+ jdk: openjdk7
15
+ - rvm: jruby-1.7
16
+ jdk: oraclejdk8
17
+ - rvm: jruby-head
18
+ jdk: oraclejdk8
19
+ - rvm: jruby-9.1.13.0
20
+ jdk: openjdk7
21
+ - rvm: jruby-9.1.13.0
22
+ jdk: oraclejdk8
11
23
  allow_failures:
24
+ - rvm: rbx-2
25
+ - rvm: rbx-3
12
26
  - rvm: ruby-head
27
+ sudo: false
28
+ addons:
29
+ apt:
30
+ packages:
31
+ - libpcre3
32
+ - libpcre3-dev
13
33
  before_install:
14
- - sudo apt-get install libpcre3 libpcre3-dev
34
+ - gem install bundler
35
+ env: JRUBY_OPTS="--server --debug -J-Xss1024k -J-Xmx652m -J-XX:+UseConcMarkSweepGC"
15
36
 
16
37
  notifications:
17
38
  irc: "irc.freenode.org#adhearsion"
@@ -1,5 +1,11 @@
1
1
  # [develop](https://github.com/benlangfeld/ruby_speech)
2
2
 
3
+ # [2.4.0](https://github.com/benlangfeld/ruby_speech/compare/v2.3.2...v2.4.0) - [2018-02-23](https://rubygems.org/gems/ruby_speech/versions/2.4.0)
4
+ * Feature: Permit percentage rate values for prosody tags
5
+ * Bugfix: Rulerefs referenced n-levels deep under Rulerefs should be expanded.
6
+ * Bugfix: Optimize performance of built-in number DTMF grammar
7
+ * Bugfix: Fix handling of millisecond values
8
+
3
9
  # [2.3.2](https://github.com/benlangfeld/ruby_speech/compare/v2.3.1...v2.3.2) - [2014-04-21](https://rubygems.org/gems/ruby_speech/versions/2.3.2)
4
10
  * Bugfix: String nodes should take non-strings and cast to a string (`#to_s`)
5
11
  * Bugfix: Cleanly handle NLSML with no input tag
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/ruby_speech.png)](https://rubygems.org/gems/ruby_speech)
2
- [![Build Status](https://secure.travis-ci.org/benlangfeld/ruby_speech.png?branch=develop)](http://travis-ci.org/benlangfeld/ruby_speech)
3
- [![Dependency Status](https://gemnasium.com/benlangfeld/ruby_speech.png?travis)](https://gemnasium.com/benlangfeld/ruby_speech)
4
- [![Code Climate](https://codeclimate.com/github/benlangfeld/ruby_speech.png)](https://codeclimate.com/github/benlangfeld/ruby_speech)
5
- [![Coverage Status](https://coveralls.io/repos/benlangfeld/ruby_speech/badge.png?branch=develop)](https://coveralls.io/r/benlangfeld/ruby_speech)
2
+ [![Build Status](https://secure.travis-ci.org/adhearsion/ruby_speech.png?branch=develop)](http://travis-ci.org/adhearsion/ruby_speech)
3
+ [![Dependency Status](https://gemnasium.com/adhearsion/ruby_speech.png?travis)](https://gemnasium.com/adhearsion/ruby_speech)
4
+ [![Code Climate](https://codeclimate.com/github/adhearsion/ruby_speech.png)](https://codeclimate.com/github/adhearsion/ruby_speech)
5
+ [![Coverage Status](https://coveralls.io/repos/adhearsion/ruby_speech/badge.png?branch=develop)](https://coveralls.io/r/adhearsion/ruby_speech)
6
6
 
7
7
  # RubySpeech
8
8
  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.
@@ -331,7 +331,7 @@ document.best_interpretation # => {
331
331
  }
332
332
  ```
333
333
 
334
- Check out the [YARD documentation](http://rdoc.info/github/benlangfeld/ruby_speech/master/frames) for more
334
+ Check out the [YARD documentation](http://rdoc.info/github/adhearsion/ruby_speech/master/frames) for more
335
335
 
336
336
  ## Features:
337
337
  ### SSML
@@ -374,10 +374,10 @@ Check out the [YARD documentation](http://rdoc.info/github/benlangfeld/ruby_spee
374
374
  * `<lexicon/>`
375
375
 
376
376
  ## Links:
377
- * [Source](https://github.com/benlangfeld/ruby_speech)
377
+ * [Source](https://github.com/adhearsion/ruby_speech)
378
378
  * [Documentation](http://rdoc.info/gems/ruby_speech/frames)
379
- * [Bug Tracker](https://github.com/benlangfeld/ruby_speech/issues)
380
- * [CI](https://travis-ci.org/#!/benlangfeld/ruby_speech)
379
+ * [Bug Tracker](https://github.com/adhearsion/ruby_speech/issues)
380
+ * [CI](https://travis-ci.org/#!/adhearsion/ruby_speech)
381
381
 
382
382
  ## Note on Patches/Pull Requests
383
383
 
@@ -1,4 +1,4 @@
1
- package com.benlangfeld.ruby_speech;
1
+ package com.adhearsion.ruby_speech;
2
2
 
3
3
  import org.jruby.Ruby;
4
4
  import org.jruby.RubyClass;
@@ -1,4 +1,4 @@
1
- package com.benlangfeld.ruby_speech;
1
+ package com.adhearsion.ruby_speech;
2
2
 
3
3
  import org.jruby.Ruby;
4
4
  import org.jruby.RubyClass;
@@ -3,7 +3,7 @@ require 'mkmf'
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-----"
6
+ abort "-----\nPCRE is missing. You must install it as per the README @ https://github.com/adhearsion/ruby_speech\n-----"
7
7
  end
8
8
 
9
9
  create_makefile 'ruby_speech/ruby_speech'
@@ -4,6 +4,8 @@ require 'ruby_speech/grxml/element'
4
4
  module RubySpeech
5
5
  module GRXML
6
6
  InvalidChildError = Class.new StandardError
7
+ MissingReferenceError = Class.new StandardError
8
+ ReferentialLoopError = Class.new StandardError
7
9
 
8
10
  GRXML_NAMESPACE = 'http://www.w3.org/2001/06/grammar'
9
11
 
@@ -57,7 +57,8 @@ module RubySpeech::GRXML::Builtins
57
57
  # @option options [#to_i] :maxlength Maximum length for the string of digits.
58
58
  # @option options [#to_i] :length Absolute length for the string of digits.
59
59
  #
60
- # @return [RubySpeech::GRXML::Grammar] a grammar for interpreting a boolean response.
60
+ # @return [RubySpeech::GRXML::Grammar] a grammar for interpreting an integer
61
+ # response.
61
62
  #
62
63
  # @raise [ArgumentError] if any of the length attributes logically conflict
63
64
  #
@@ -118,22 +119,28 @@ module RubySpeech::GRXML::Builtins
118
119
  def self.number(options = nil)
119
120
  RubySpeech::GRXML.draw mode: :dtmf, root: 'number' do
120
121
  rule id: 'number', scope: 'public' do
121
- item repeat: '0-' do
122
- ruleref uri: '#digit'
122
+ one_of do
123
+ item { ruleref uri: '#less_than_one' }
124
+ item { ruleref uri: '#one_or_more' }
123
125
  end
126
+ end
127
+
128
+ rule id: 'less_than_one' do
129
+ item { '*' }
130
+ item { ruleref uri: '#digit_series' }
131
+ end
132
+
133
+ rule id: 'one_or_more' do
134
+ item { ruleref uri: '#digit_series' }
124
135
  item repeat: '0-1' do
125
136
  item { '*' }
126
- item repeat: '0-' do
127
- ruleref uri: '#digit'
128
- end
137
+ item(repeat: '0-1') { ruleref uri: '#digit_series' }
129
138
  end
130
139
  end
131
140
 
132
- rule id: 'digit' do
133
- one_of do
134
- 0.upto(9) { |d| item { d.to_s } }
135
- end
136
- end
141
+ rule(id: 'digit_series') { item(repeat: '1-') { ruleref uri: '#digit' } }
142
+
143
+ rule(id: 'digit') { one_of { 0.upto(9) { |d| item { d.to_s } } } }
137
144
  end
138
145
  end
139
146
 
@@ -113,17 +113,39 @@ module RubySpeech
113
113
  # Replaces rulerefs in the document with a copy of the original rule.
114
114
  # Removes all top level rules except the root rule
115
115
  #
116
+ # @raises [MissingReferenceError] if a ruleref references a rule that is
117
+ # not defined.
118
+ # @raises [ReferentialLoopError] if rulerefs create a referencial cycle.
119
+ #
116
120
  # @return self
117
121
  #
118
122
  def inline!
119
- xpath("//ns:ruleref", :ns => GRXML_NAMESPACE).each do |ref|
120
- rule = rule_with_id ref[:uri].sub(/^#/, '')
121
- ref.swap rule.dup.children
123
+ previous_uris = {}
124
+ loop do
125
+ rule = nil
126
+ uris = {}
127
+ xpath('//ns:ruleref', ns: GRXML_NAMESPACE).each do |ref|
128
+ uri = ref[:uri].sub(/^#/, '')
129
+ uris[uri] = 1
130
+ rule = rule_with_id uri
131
+ unless rule
132
+ raise MissingReferenceError,
133
+ "Ruleref '##{uri}' is referenced but not defined"
134
+ end
135
+ ref.swap rule.dup.children
136
+ end
137
+ break unless rule
138
+ if previous_uris.keys.eql? uris.keys
139
+ raise ReferentialLoopError,
140
+ 'GRXML document contains cycles with ruleref(s): ' <<
141
+ uris.keys.join(', ')
142
+ end
143
+ previous_uris = uris
122
144
  end
123
145
 
124
146
  query = "./ns:rule[@id!='#{root}']"
125
147
  query += "|./ns:rule[@ns:id!='#{root}']" if Nokogiri.jruby?
126
- non_root_rules = xpath query, :ns => namespace_href
148
+ non_root_rules = xpath query, ns: namespace_href
127
149
  non_root_rules.remove
128
150
 
129
151
  self
@@ -6,7 +6,7 @@ require 'ruby_speech/ruby_speech'
6
6
 
7
7
  if RUBY_PLATFORM =~ /java/
8
8
  require 'jruby'
9
- com.benlangfeld.ruby_speech.RubySpeechService.new.basicLoad(JRuby.runtime)
9
+ com.adhearsion.ruby_speech.RubySpeechService.new.basicLoad(JRuby.runtime)
10
10
  end
11
11
 
12
12
  module RubySpeech
@@ -36,7 +36,7 @@ module RubySpeech
36
36
  # @return [Float]
37
37
  #
38
38
  def time
39
- read_attr :time, :to_f
39
+ get_time_attribute :time
40
40
  end
41
41
 
42
42
  ##
@@ -50,7 +50,6 @@ module RubySpeech
50
50
 
51
51
  def <<(*args)
52
52
  raise InvalidChildError, "A Break cannot contain children"
53
- super
54
53
  end
55
54
 
56
55
  def eql?(o)
@@ -23,9 +23,21 @@ module RubySpeech
23
23
 
24
24
  private
25
25
 
26
+ def get_time_attribute(key)
27
+ value = read_attr(key)
28
+
29
+ if value.nil?
30
+ nil
31
+ elsif value.end_with?('ms')
32
+ value.to_f / 1000
33
+ else
34
+ value.to_f
35
+ end
36
+ end
37
+
26
38
  def set_time_attribute(key, value)
27
39
  raise ArgumentError, "You must specify a valid #{key} (positive float value in seconds)" unless value.is_a?(Numeric) && value >= 0
28
- self[key] = "#{value}s"
40
+ self[key] = value == value.round ? "#{value.to_i}s" : "#{(value * 1000).to_i}ms"
29
41
  end
30
42
  end # Element
31
43
  end # SSML
@@ -34,7 +34,6 @@ module RubySpeech
34
34
 
35
35
  def <<(*args)
36
36
  raise InvalidChildError, "A Mark cannot contain children"
37
- super
38
37
  end
39
38
 
40
39
  def eql?(o)
@@ -102,27 +102,29 @@ module RubySpeech
102
102
  end
103
103
 
104
104
  ##
105
- # A change in the speaking rate for the contained text. Legal values are: a relative change or "x-slow", "slow", "medium", "fast", "x-fast", or "default". Labels "x-slow" through "x-fast" represent a sequence of monotonically non-decreasing speaking rates. When a number is used to specify a relative change it acts as a multiplier of the default rate. For example, a value of 1 means no change in speaking rate, a value of 2 means a speaking rate twice the default rate, and a value of 0.5 means a speaking rate of half the default rate. The default rate for a voice depends on the language and dialect and on the personality of the voice. The default rate for a voice should be such that it is experienced as a normal speaking rate for the voice when reading aloud text. Since voices are processor-specific, the default rate will be as well.
105
+ # A change in the speaking rate for the contained text. Legal values are: a relative change or "x-slow", "slow", "medium", "fast", "x-fast", or "default". Labels "x-slow" through "x-fast" represent a sequence of monotonically non-decreasing speaking rates. When a number is used to specify a relative change it acts as a multiplier of the default rate. For example, a value of 1 means no change in speaking rate, a value of 2 means a speaking rate twice the default rate, and a value of 0.5 means a speaking rate of half the default rate. Further, changes can be specified as percentages (e.g. '10%' or '+15%'), but these are the only string entries permitted. The default rate for a voice depends on the language and dialect and on the personality of the voice. The default rate for a voice should be such that it is experienced as a normal speaking rate for the voice when reading aloud text. Since voices are processor-specific, the default rate will be as well.
106
106
  #
107
- # @return [Symbol, Float]
107
+ # @return [Symbol, Float, String]
108
108
  #
109
109
  def rate
110
110
  value = read_attr :rate
111
111
  return unless value
112
112
  if VALID_RATES.include?(value.to_sym)
113
113
  value.to_sym
114
+ elsif value.include? "%"
115
+ value
114
116
  else
115
117
  value.to_f
116
118
  end
117
119
  end
118
120
 
119
121
  ##
120
- # @param [Symbol, Numeric] v
122
+ # @param [Symbol, Numeric, String] v
121
123
  #
122
124
  # @raises ArgumentError if v is not either a positive Numeric or one of VALID_RATES
123
125
  #
124
126
  def rate=(v)
125
- raise ArgumentError, "You must specify a valid rate ([positive-number](multiplier), #{VALID_RATES.map(&:inspect).join ', '})" unless (v.is_a?(Numeric) && v >= 0) || VALID_RATES.include?(v)
127
+ raise ArgumentError, "You must specify a valid rate ([positive-number](multiplier), #{VALID_RATES.map(&:inspect).join ', '})" unless (v.is_a?(Numeric) && v >= 0) || VALID_RATES.include?(v) || (v.is_a?(String) && v.include?("%"))
126
128
  self[:rate] = v
127
129
  end
128
130
 
@@ -132,7 +134,8 @@ module RubySpeech
132
134
  # @return [Integer]
133
135
  #
134
136
  def duration
135
- read_attr :duration, :to_i
137
+ value = get_time_attribute :duration
138
+ value.round if value
136
139
  end
137
140
 
138
141
  ##
@@ -1,3 +1,3 @@
1
1
  module RubySpeech
2
- VERSION = "2.3.2"
2
+ VERSION = "2.4.0"
3
3
  end
@@ -7,10 +7,10 @@ Gem::Specification.new do |s|
7
7
  s.version = RubySpeech::VERSION
8
8
  s.authors = ["Ben Langfeld"]
9
9
  s.email = ["ben@langfeld.me"]
10
- s.homepage = "https://github.com/benlangfeld/ruby_speech"
10
+ s.homepage = "https://github.com/adhearsion/ruby_speech"
11
11
  s.summary = %q{A Ruby library for TTS & ASR document preparation}
12
12
  s.description = %q{Prepare SSML and GRXML documents with ease}
13
-
13
+
14
14
  s.license = 'MIT'
15
15
 
16
16
  s.rubyforge_project = "ruby_speech"
@@ -27,18 +27,25 @@ Gem::Specification.new do |s|
27
27
  s.extensions = ['ext/ruby_speech/extconf.rb']
28
28
  end
29
29
 
30
- s.add_runtime_dependency %q<nokogiri>, ["~> 1.6"]
30
+ s.add_runtime_dependency %q<nokogiri>, ["~> 1.6.0"]
31
31
  s.add_runtime_dependency %q<activesupport>, [">= 3.0.7", "< 5.0.0"]
32
32
 
33
33
  s.add_development_dependency %q<bundler>, [">= 1.0.0"]
34
- s.add_development_dependency %q<rspec>, [">= 2.7"]
35
- s.add_development_dependency %q<ci_reporter>, [">= 1.6.3"]
34
+ s.add_development_dependency %q<rspec>, ["~> 2.99.0"]
35
+ s.add_development_dependency %q<rspec-its>, [">= 0"]
36
+ s.add_development_dependency %q<ci_reporter>, ["~> 1.6"]
36
37
  s.add_development_dependency %q<yard>, [">= 0.7.0"]
37
- s.add_development_dependency %q<rake>, [">= 0"]
38
+ s.add_development_dependency %q<rake>, ["< 11.0"]
38
39
  s.add_development_dependency %q<guard>, [">= 0.9.0"]
39
40
  s.add_development_dependency %q<guard-rspec>, [">= 0"]
41
+ s.add_development_dependency %q<listen>, ["< 3.1.0"]
40
42
  s.add_development_dependency %q<ruby_gntp>, [">= 0"]
41
43
  s.add_development_dependency %q<guard-rake>, [">= 0"]
42
44
  s.add_development_dependency %q<rake-compiler>, [">= 0"]
43
45
  s.add_development_dependency %q<coveralls>, [">= 0"]
46
+
47
+ if RUBY_VERSION < '2.0'
48
+ s.add_development_dependency %q<term-ansicolor>, ["< 1.3.1"]
49
+ s.add_development_dependency %q<tins>, ["~> 1.6.0"]
50
+ end
44
51
  end
@@ -119,22 +119,31 @@ describe RubySpeech::GRXML::Builtins do
119
119
  it { should not_match('#') }
120
120
  end
121
121
 
122
- describe "number" do
122
+ describe 'number' do
123
123
  subject(:grammar) { described_class.number }
124
124
 
125
- it { should match('0').and_interpret_as('dtmf-0') }
126
- it { should match('123').and_interpret_as('dtmf-1 dtmf-2 dtmf-3') }
127
- it { should match('1*01').and_interpret_as('dtmf-1 dtmf-star dtmf-0 dtmf-1') }
128
- it { should match('01*00').and_interpret_as('dtmf-0 dtmf-1 dtmf-star dtmf-0 dtmf-0') }
129
- it { should match('100000000000*00').and_interpret_as('dtmf-1 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-star dtmf-0 dtmf-0') }
130
- it { should match('0*08').and_interpret_as('dtmf-0 dtmf-star dtmf-0 dtmf-8') }
131
- it { should match('*59').and_interpret_as('dtmf-star dtmf-5 dtmf-9') }
132
- it { should match('0*0').and_interpret_as('dtmf-0 dtmf-star dtmf-0') }
133
- it { should match('10*5').and_interpret_as('dtmf-1 dtmf-0 dtmf-star dtmf-5') }
134
- it { should match('123*').and_interpret_as('dtmf-1 dtmf-2 dtmf-3 dtmf-star') }
135
- it { should match('123*2342').and_interpret_as('dtmf-1 dtmf-2 dtmf-3 dtmf-star dtmf-2 dtmf-3 dtmf-4 dtmf-2') }
125
+ it { should match('0').and_interpret_as 'dtmf-0' }
126
+ it { should match('123').and_interpret_as 'dtmf-1 dtmf-2 dtmf-3' }
127
+ it { should match('1*01').and_interpret_as dtmf_seq %w(1 star 0 1) }
128
+ it { should match('01*00').and_interpret_as dtmf_seq %w(0 1 star 0 0) }
129
+ it do
130
+ should match('100000000000*00')
131
+ .and_interpret_as dtmf_seq %w(1 0 0 0 0 0 0 0 0 0 0 0 star 0 0)
132
+ end
133
+ it { should match('0*08').and_interpret_as dtmf_seq %w(0 star 0 8) }
134
+ it { should match('*59').and_interpret_as 'dtmf-star dtmf-5 dtmf-9' }
135
+ it { should match('0*0').and_interpret_as 'dtmf-0 dtmf-star dtmf-0' }
136
+ it { should match('10*5').and_interpret_as dtmf_seq %w(1 0 star 5) }
137
+ it { should match('123*').and_interpret_as dtmf_seq %w(1 2 3 star) }
138
+ it do
139
+ should match('123*2342').and_interpret_as dtmf_seq %w(1 2 3 star 2 3 4 2)
140
+ end
136
141
 
137
- it { should not_match('#') }
142
+ it { should potentially_match '*' }
143
+
144
+ it { should not_match '#' }
145
+ it { should not_match '**' }
146
+ it { should not_match '0123*456*789' }
138
147
  end
139
148
 
140
149
  describe "phone" do
@@ -232,6 +232,140 @@ module RubySpeech
232
232
  grammar.inline!.should == inline_grammar
233
233
  grammar.should == inline_grammar
234
234
  end
235
+
236
+ context 'nested' do
237
+ let :expected_doc do
238
+ RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
239
+ rule id: :main, scope: 'public' do
240
+ string "How about an oatmeal cookie? You'll feel better."
241
+ end
242
+ end
243
+ end
244
+
245
+ context '1 level deep' do
246
+ subject do
247
+ RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
248
+ rule id: :main, scope: 'public' do
249
+ ruleref uri: '#rabbit_hole2'
250
+ end
251
+ rule id: 'rabbit_hole2' do
252
+ string "How about an oatmeal cookie? You'll feel better."
253
+ end
254
+ end.inline
255
+ end
256
+
257
+ it { should eq expected_doc }
258
+ end
259
+
260
+ context '2 levels deep' do
261
+ subject do
262
+ RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
263
+ rule id: :main, scope: 'public' do
264
+ ruleref uri: '#rabbit_hole2'
265
+ end
266
+ rule id: 'rabbit_hole2' do
267
+ ruleref uri: '#rabbit_hole3'
268
+ end
269
+ rule id: 'rabbit_hole3' do
270
+ string "How about an oatmeal cookie? You'll feel better."
271
+ end
272
+ end.inline
273
+ end
274
+
275
+ it { should eq expected_doc }
276
+ end
277
+
278
+ context '3 levels deep' do
279
+ subject do
280
+ RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
281
+ rule id: :main, scope: 'public' do
282
+ ruleref uri: '#rabbit_hole2'
283
+ end
284
+ rule id: 'rabbit_hole2' do
285
+ ruleref uri: '#rabbit_hole3'
286
+ end
287
+ rule id: 'rabbit_hole3' do
288
+ ruleref uri: '#rabbit_hole4'
289
+ end
290
+ rule id: 'rabbit_hole4' do
291
+ string "How about an oatmeal cookie? You'll feel better."
292
+ end
293
+ end.inline
294
+ end
295
+
296
+ it { should eq expected_doc }
297
+ end
298
+
299
+ context 'in a self-referencial infinite loop' do
300
+ subject do
301
+ RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
302
+ rule id: :main, scope: 'public' do
303
+ ruleref uri: '#paradox'
304
+ end
305
+ rule id: 'paradox' do
306
+ ruleref uri: '#paradox'
307
+ end
308
+ end.inline
309
+ end
310
+
311
+ it 'should raise an Exception' do
312
+ expect { subject }
313
+ .to raise_error RubySpeech::GRXML::ReferentialLoopError
314
+ end
315
+ end
316
+
317
+ context 'in a cross-referencial infinite loop' do
318
+ subject do
319
+ RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
320
+ rule id: :main, scope: 'public' do
321
+ ruleref uri: '#007'
322
+ end
323
+ rule id: '007' do
324
+ one_of do
325
+ item do
326
+ ruleref uri: '#bond'
327
+ end
328
+ end
329
+ end
330
+ rule id: 'bond' do
331
+ one_of do
332
+ item do
333
+ ruleref uri: '#james_bond'
334
+ end
335
+ end
336
+ end
337
+ rule id: 'james_bond' do
338
+ one_of do
339
+ item do
340
+ ruleref uri: '#007'
341
+ end
342
+ end
343
+ end
344
+ end.inline
345
+ end
346
+
347
+ it 'should raise an Exception' do
348
+ expect { subject }
349
+ .to raise_error RubySpeech::GRXML::ReferentialLoopError
350
+ end
351
+ end
352
+
353
+ context 'with an invalid-reference' do
354
+ subject do
355
+ RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
356
+ rule id: :main, scope: 'public' do
357
+ ruleref uri: '#lost'
358
+ end
359
+ end.inline
360
+ end
361
+
362
+ it 'should raise a descriptive exception' do
363
+ expect { subject }
364
+ .to raise_error RubySpeech::GRXML::MissingReferenceError,
365
+ "Ruleref '#lost' is referenced but not defined"
366
+ end
367
+ end
368
+ end
235
369
  end
236
370
 
237
371
  describe "#tokenize!" do
@@ -516,6 +516,50 @@ module RubySpeech
516
516
  end
517
517
  end
518
518
 
519
+ context "with a grammar that takes a a specific digit repeated within a range" do
520
+ let(:grammar) do
521
+ GRXML.draw :mode => :dtmf, :root => 'digits' do
522
+ rule :id => 'digits' do
523
+ item :repeat => 0..3 do
524
+ '6'
525
+ end
526
+ end
527
+ end
528
+ end
529
+
530
+ {
531
+ '' => '',
532
+ '6' => 'dtmf-6',
533
+ '66' => 'dtmf-6 dtmf-6',
534
+ }.each_pair do |input, interpretation|
535
+ it "should match '#{input}'" do
536
+ expected_match = GRXML::Match.new :mode => :dtmf,
537
+ :confidence => 1,
538
+ :utterance => input,
539
+ :interpretation => interpretation
540
+ subject.match(input).should == expected_match
541
+ end
542
+ end
543
+
544
+ {
545
+ '666' => 'dtmf-6 dtmf-6 dtmf-6',
546
+ }.each_pair do |input, interpretation|
547
+ it "should maximally match '#{input}'" do
548
+ expected_match = GRXML::MaxMatch.new :mode => :dtmf,
549
+ :confidence => 1,
550
+ :utterance => input,
551
+ :interpretation => interpretation
552
+ subject.match(input).should == expected_match
553
+ end
554
+ end
555
+
556
+ %w{6666 7}.each do |input|
557
+ it "should not match '#{input}'" do
558
+ subject.match(input).should == GRXML::NoMatch.new
559
+ end
560
+ end
561
+ end
562
+
519
563
  context "with a grammar that takes a a specific digit repeated within a range, followed by specific digit" do
520
564
  let(:grammar) do
521
565
  GRXML.draw :mode => :dtmf, :root => 'digits' do
@@ -21,14 +21,28 @@ module RubySpeech
21
21
  end
22
22
 
23
23
  describe "from a document" do
24
- let(:document) { '<break strength="strong" time="3"/>' }
25
-
26
24
  subject { Element.import document }
27
25
 
28
- it { should be_instance_of Break }
26
+ context 'with time of 3' do
27
+ let(:document) { '<break strength="strong" time="3"/>' }
29
28
 
30
- its(:strength) { should == :strong }
31
- its(:time) { should == 3 }
29
+ it { should be_instance_of Break }
30
+
31
+ its(:strength) { should == :strong }
32
+ its(:time) { should eql 3.0 }
33
+ end
34
+
35
+ context 'with time of 4s' do
36
+ let(:document) { '<break time="4s"/>' }
37
+
38
+ its(:time) { should eql 4.0 }
39
+ end
40
+
41
+ context 'with time of 5555ms' do
42
+ let(:document) { '<break time="5555ms"/>' }
43
+
44
+ its(:time) { should eql 5.555 }
45
+ end
32
46
  end
33
47
 
34
48
  describe "#strength" do
@@ -51,10 +65,16 @@ module RubySpeech
51
65
  end
52
66
 
53
67
  describe "#time" do
54
- context "with a valid value" do
68
+ context "with a valid whole seconds value of 3" do
55
69
  before { subject.time = 3 }
56
70
 
57
- its(:time) { should == 3 }
71
+ its(:time) { should eql 3.0 }
72
+ end
73
+
74
+ context "with a valid fractional seconds value of 3.5" do
75
+ before { subject.time = 3.5 }
76
+
77
+ its(:time) { should eql 3.5 }
58
78
  end
59
79
 
60
80
  context "with a negative value" do
@@ -16,7 +16,7 @@ module RubySpeech
16
16
  its(:contour) { should == 'something' }
17
17
  its(:range) { should == '20Hz' }
18
18
  its(:rate) { should == 2 }
19
- its(:duration) { should == 10 }
19
+ its(:duration) { should eql 10 }
20
20
  its(:volume) { should == :loud }
21
21
  end
22
22
 
@@ -35,7 +35,7 @@ module RubySpeech
35
35
  its(:contour) { should == 'something' }
36
36
  its(:range) { should == '20Hz' }
37
37
  its(:rate) { should == 2 }
38
- its(:duration) { should == 10 }
38
+ its(:duration) { should eql 10 }
39
39
  its(:volume) { should == :loud }
40
40
  end
41
41
 
@@ -149,6 +149,24 @@ module RubySpeech
149
149
  it "with a negative value" do
150
150
  lambda { subject.rate = -100 }.should raise_error(ArgumentError, "You must specify a valid rate ([positive-number](multiplier), :\"x-slow\", :slow, :medium, :fast, :\"x-fast\", :default)")
151
151
  end
152
+
153
+ describe "with a percentage" do
154
+ before { subject.rate = "22.5%" }
155
+
156
+ its(:rate) { should == "22.5%" }
157
+ end
158
+
159
+ describe "with a percentage and a plus sign" do
160
+ before { subject.rate = "+22.5%" }
161
+
162
+ its(:rate) { should == "+22.5%" }
163
+ end
164
+
165
+ describe "with a percentage and a minus sign" do
166
+ before { subject.rate = "-22.5%" }
167
+
168
+ its(:rate) { should == "-22.5%" }
169
+ end
152
170
  end
153
171
  end
154
172
 
@@ -156,7 +174,7 @@ module RubySpeech
156
174
  context "with a valid value" do
157
175
  before { subject.duration = 3 }
158
176
 
159
- its(:duration) { should == 3 }
177
+ its(:duration) { should eql 3 }
160
178
  end
161
179
 
162
180
  context "with a negative value" do
@@ -1,8 +1,14 @@
1
- require 'ruby_speech'
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
- require 'coveralls'
4
+ require "coveralls"
4
5
  Coveralls.wear!
5
6
 
7
+ %w{
8
+ rspec/its
9
+ ruby_speech
10
+ }.each { |f| require f }
11
+
6
12
  Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
7
13
 
8
14
  schema_file_path = File.expand_path File.join(__FILE__, '../../assets/synthesis.xsd')
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # Convert a simple DTMF string from "1 star 2" to "dtmf-1 dtmf-star dtmf-2".
6
+ #
7
+ # @param [Array] sequence A set of DTMF keys, such as `%w(1 star 2)`.
8
+ #
9
+ # @return [String] A string with "dtmf-" prefixed for each DTMF element.
10
+ # Example: "dtmf-1 dtmf-star dtmf-2".
11
+ #
12
+ def dtmf_seq(sequence)
13
+ sequence.map { |d| "dtmf-#{d}" }.join ' '
14
+ end
metadata CHANGED
@@ -1,203 +1,231 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_speech
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 2.4.0
5
5
  platform: java
6
6
  authors:
7
7
  - Ben Langfeld
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-21 00:00:00.000000000 Z
11
+ date: 2018-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 1.6.0
14
19
  name: nokogiri
20
+ prerelease: false
21
+ type: :runtime
15
22
  version_requirements: !ruby/object:Gem::Requirement
16
23
  requirements:
17
- - - ~>
24
+ - - "~>"
18
25
  - !ruby/object:Gem::Version
19
- version: '1.6'
26
+ version: 1.6.0
27
+ - !ruby/object:Gem::Dependency
20
28
  requirement: !ruby/object:Gem::Requirement
21
29
  requirements:
22
- - - ~>
30
+ - - ">="
23
31
  - !ruby/object:Gem::Version
24
- version: '1.6'
32
+ version: 3.0.7
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: 5.0.0
36
+ name: activesupport
25
37
  prerelease: false
26
38
  type: :runtime
27
- - !ruby/object:Gem::Dependency
28
- name: activesupport
29
39
  version_requirements: !ruby/object:Gem::Requirement
30
40
  requirements:
31
- - - '>='
41
+ - - ">="
32
42
  - !ruby/object:Gem::Version
33
43
  version: 3.0.7
34
- - - <
44
+ - - "<"
35
45
  - !ruby/object:Gem::Version
36
46
  version: 5.0.0
47
+ - !ruby/object:Gem::Dependency
37
48
  requirement: !ruby/object:Gem::Requirement
38
49
  requirements:
39
- - - '>='
50
+ - - ">="
40
51
  - !ruby/object:Gem::Version
41
- version: 3.0.7
42
- - - <
43
- - !ruby/object:Gem::Version
44
- version: 5.0.0
45
- prerelease: false
46
- type: :runtime
47
- - !ruby/object:Gem::Dependency
52
+ version: 1.0.0
48
53
  name: bundler
54
+ prerelease: false
55
+ type: :development
49
56
  version_requirements: !ruby/object:Gem::Requirement
50
57
  requirements:
51
- - - '>='
58
+ - - ">="
52
59
  - !ruby/object:Gem::Version
53
60
  version: 1.0.0
61
+ - !ruby/object:Gem::Dependency
54
62
  requirement: !ruby/object:Gem::Requirement
55
63
  requirements:
56
- - - '>='
64
+ - - "~>"
57
65
  - !ruby/object:Gem::Version
58
- version: 1.0.0
66
+ version: 2.99.0
67
+ name: rspec
59
68
  prerelease: false
60
69
  type: :development
61
- - !ruby/object:Gem::Dependency
62
- name: rspec
63
70
  version_requirements: !ruby/object:Gem::Requirement
64
71
  requirements:
65
- - - '>='
72
+ - - "~>"
66
73
  - !ruby/object:Gem::Version
67
- version: '2.7'
74
+ version: 2.99.0
75
+ - !ruby/object:Gem::Dependency
68
76
  requirement: !ruby/object:Gem::Requirement
69
77
  requirements:
70
- - - '>='
78
+ - - ">="
71
79
  - !ruby/object:Gem::Version
72
- version: '2.7'
80
+ version: '0'
81
+ name: rspec-its
73
82
  prerelease: false
74
83
  type: :development
75
- - !ruby/object:Gem::Dependency
76
- name: ci_reporter
77
84
  version_requirements: !ruby/object:Gem::Requirement
78
85
  requirements:
79
- - - '>='
86
+ - - ">="
80
87
  - !ruby/object:Gem::Version
81
- version: 1.6.3
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
82
90
  requirement: !ruby/object:Gem::Requirement
83
91
  requirements:
84
- - - '>='
92
+ - - "~>"
85
93
  - !ruby/object:Gem::Version
86
- version: 1.6.3
94
+ version: '1.6'
95
+ name: ci_reporter
87
96
  prerelease: false
88
97
  type: :development
89
- - !ruby/object:Gem::Dependency
90
- name: yard
91
98
  version_requirements: !ruby/object:Gem::Requirement
92
99
  requirements:
93
- - - '>='
100
+ - - "~>"
94
101
  - !ruby/object:Gem::Version
95
- version: 0.7.0
102
+ version: '1.6'
103
+ - !ruby/object:Gem::Dependency
96
104
  requirement: !ruby/object:Gem::Requirement
97
105
  requirements:
98
- - - '>='
106
+ - - ">="
99
107
  - !ruby/object:Gem::Version
100
108
  version: 0.7.0
109
+ name: yard
101
110
  prerelease: false
102
111
  type: :development
103
- - !ruby/object:Gem::Dependency
104
- name: rake
105
112
  version_requirements: !ruby/object:Gem::Requirement
106
113
  requirements:
107
- - - '>='
114
+ - - ">="
108
115
  - !ruby/object:Gem::Version
109
- version: '0'
116
+ version: 0.7.0
117
+ - !ruby/object:Gem::Dependency
110
118
  requirement: !ruby/object:Gem::Requirement
111
119
  requirements:
112
- - - '>='
120
+ - - "<"
113
121
  - !ruby/object:Gem::Version
114
- version: '0'
122
+ version: '11.0'
123
+ name: rake
115
124
  prerelease: false
116
125
  type: :development
117
- - !ruby/object:Gem::Dependency
118
- name: guard
119
126
  version_requirements: !ruby/object:Gem::Requirement
120
127
  requirements:
121
- - - '>='
128
+ - - "<"
122
129
  - !ruby/object:Gem::Version
123
- version: 0.9.0
130
+ version: '11.0'
131
+ - !ruby/object:Gem::Dependency
124
132
  requirement: !ruby/object:Gem::Requirement
125
133
  requirements:
126
- - - '>='
134
+ - - ">="
127
135
  - !ruby/object:Gem::Version
128
136
  version: 0.9.0
137
+ name: guard
129
138
  prerelease: false
130
139
  type: :development
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: 0.9.0
131
145
  - !ruby/object:Gem::Dependency
146
+ requirement: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
132
151
  name: guard-rspec
152
+ prerelease: false
153
+ type: :development
133
154
  version_requirements: !ruby/object:Gem::Requirement
134
155
  requirements:
135
- - - '>='
156
+ - - ">="
136
157
  - !ruby/object:Gem::Version
137
158
  version: '0'
159
+ - !ruby/object:Gem::Dependency
138
160
  requirement: !ruby/object:Gem::Requirement
139
161
  requirements:
140
- - - '>='
162
+ - - "<"
141
163
  - !ruby/object:Gem::Version
142
- version: '0'
164
+ version: 3.1.0
165
+ name: listen
143
166
  prerelease: false
144
167
  type: :development
145
- - !ruby/object:Gem::Dependency
146
- name: ruby_gntp
147
168
  version_requirements: !ruby/object:Gem::Requirement
148
169
  requirements:
149
- - - '>='
170
+ - - "<"
150
171
  - !ruby/object:Gem::Version
151
- version: '0'
172
+ version: 3.1.0
173
+ - !ruby/object:Gem::Dependency
152
174
  requirement: !ruby/object:Gem::Requirement
153
175
  requirements:
154
- - - '>='
176
+ - - ">="
155
177
  - !ruby/object:Gem::Version
156
178
  version: '0'
179
+ name: ruby_gntp
157
180
  prerelease: false
158
181
  type: :development
159
- - !ruby/object:Gem::Dependency
160
- name: guard-rake
161
182
  version_requirements: !ruby/object:Gem::Requirement
162
183
  requirements:
163
- - - '>='
184
+ - - ">="
164
185
  - !ruby/object:Gem::Version
165
186
  version: '0'
187
+ - !ruby/object:Gem::Dependency
166
188
  requirement: !ruby/object:Gem::Requirement
167
189
  requirements:
168
- - - '>='
190
+ - - ">="
169
191
  - !ruby/object:Gem::Version
170
192
  version: '0'
193
+ name: guard-rake
171
194
  prerelease: false
172
195
  type: :development
173
- - !ruby/object:Gem::Dependency
174
- name: rake-compiler
175
196
  version_requirements: !ruby/object:Gem::Requirement
176
197
  requirements:
177
- - - '>='
198
+ - - ">="
178
199
  - !ruby/object:Gem::Version
179
200
  version: '0'
201
+ - !ruby/object:Gem::Dependency
180
202
  requirement: !ruby/object:Gem::Requirement
181
203
  requirements:
182
- - - '>='
204
+ - - ">="
183
205
  - !ruby/object:Gem::Version
184
206
  version: '0'
207
+ name: rake-compiler
185
208
  prerelease: false
186
209
  type: :development
187
- - !ruby/object:Gem::Dependency
188
- name: coveralls
189
210
  version_requirements: !ruby/object:Gem::Requirement
190
211
  requirements:
191
- - - '>='
212
+ - - ">="
192
213
  - !ruby/object:Gem::Version
193
214
  version: '0'
215
+ - !ruby/object:Gem::Dependency
194
216
  requirement: !ruby/object:Gem::Requirement
195
217
  requirements:
196
- - - '>='
218
+ - - ">="
197
219
  - !ruby/object:Gem::Version
198
220
  version: '0'
221
+ name: coveralls
199
222
  prerelease: false
200
223
  type: :development
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - ">="
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
201
229
  description: Prepare SSML and GRXML documents with ease
202
230
  email:
203
231
  - ben@langfeld.me
@@ -205,10 +233,10 @@ executables: []
205
233
  extensions: []
206
234
  extra_rdoc_files: []
207
235
  files:
208
- - .gitignore
209
- - .hound.yml
210
- - .rspec
211
- - .travis.yml
236
+ - ".gitignore"
237
+ - ".hound.yml"
238
+ - ".rspec"
239
+ - ".travis.yml"
212
240
  - CHANGELOG.md
213
241
  - Gemfile
214
242
  - Guardfile
@@ -244,6 +272,7 @@ files:
244
272
  - lib/ruby_speech/nlsml.rb
245
273
  - lib/ruby_speech/nlsml/builder.rb
246
274
  - lib/ruby_speech/nlsml/document.rb
275
+ - lib/ruby_speech/ruby_speech.jar
247
276
  - lib/ruby_speech/ssml.rb
248
277
  - lib/ruby_speech/ssml/audio.rb
249
278
  - lib/ruby_speech/ssml/break.rb
@@ -293,11 +322,11 @@ files:
293
322
  - spec/ruby_speech/ssml_spec.rb
294
323
  - spec/ruby_speech_spec.rb
295
324
  - spec/spec_helper.rb
325
+ - spec/support/dtmf_helper.rb
296
326
  - spec/support/grammar_matchers.rb
297
327
  - spec/support/match_examples.rb
298
328
  - spec/support/matchers.rb
299
- - lib/ruby_speech/ruby_speech.jar
300
- homepage: https://github.com/benlangfeld/ruby_speech
329
+ homepage: https://github.com/adhearsion/ruby_speech
301
330
  licenses:
302
331
  - MIT
303
332
  metadata: {}
@@ -307,17 +336,17 @@ require_paths:
307
336
  - lib
308
337
  required_ruby_version: !ruby/object:Gem::Requirement
309
338
  requirements:
310
- - - '>='
339
+ - - ">="
311
340
  - !ruby/object:Gem::Version
312
341
  version: '0'
313
342
  required_rubygems_version: !ruby/object:Gem::Requirement
314
343
  requirements:
315
- - - '>='
344
+ - - ">="
316
345
  - !ruby/object:Gem::Version
317
346
  version: '0'
318
347
  requirements: []
319
348
  rubyforge_project: ruby_speech
320
- rubygems_version: 2.1.9
349
+ rubygems_version: 2.6.14
321
350
  signing_key:
322
351
  specification_version: 4
323
352
  summary: A Ruby library for TTS & ASR document preparation
@@ -353,7 +382,7 @@ test_files:
353
382
  - spec/ruby_speech/ssml_spec.rb
354
383
  - spec/ruby_speech_spec.rb
355
384
  - spec/spec_helper.rb
385
+ - spec/support/dtmf_helper.rb
356
386
  - spec/support/grammar_matchers.rb
357
387
  - spec/support/match_examples.rb
358
388
  - spec/support/matchers.rb
359
- has_rdoc: