pocketsphinx-ruby 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3bf38b30cbc9fd5c2375d2c330238d1ad429e44c
4
- data.tar.gz: 82aecda7d2c95378f15f47cc897b13419b83ce00
3
+ metadata.gz: d3479a20de1bf075e2a4d2efcf8721c05a650751
4
+ data.tar.gz: a3ea68aaf9e0dc60149c2992dd8316233d8568f3
5
5
  SHA512:
6
- metadata.gz: 2bb177461a17173815f299d3b17807014b80a22c3fae818569a4d29355e33dd506d3e1d4d195f8fa84ee09073014212fadd17a00e3f088a82d4278ccceea936a
7
- data.tar.gz: 1ba9d9b74c999a05091e870b0fe2aee6c45df623b4d84a7364268eab1e4cf4e41dcf11b7206e90f5e3afd1d9ee292e503f8b4a6712b859e151e611944fe867a4
6
+ metadata.gz: e732d04275721ed223776c7d90b97894e8a778e73e334a036561715efbf868b65e8b20809730013fcaf020f21ab5de2fa646af6b7bc7aeb2f467345b6492f33e
7
+ data.tar.gz: a6670826d281b272ea29d4d609805328d2da8af4753d66349e78f222c5c99eaf05a7dde19faad8ac070b57e03aacab20396c5686c8b7365e4d586591bc958add
data/README.md CHANGED
@@ -56,7 +56,7 @@ Or install it yourself as:
56
56
  The `LiveSpeechRecognizer` is modeled on the same class in [Sphinx4](http://cmusphinx.sourceforge.net/wiki/tutorialsphinx4). It uses the `Microphone` and `Decoder` classes internally to provide a simple, high-level recognition interface:
57
57
 
58
58
  ```ruby
59
- require 'pocketsphinx-ruby'
59
+ require 'pocketsphinx-ruby' # Omitted in subsequent examples
60
60
 
61
61
  Pocketsphinx::LiveSpeechRecognizer.new.recognize do |speech|
62
62
  puts speech
@@ -106,7 +106,7 @@ The `Microphone` class uses Pocketsphinx's libsphinxad to record audio for speec
106
106
  For example, to record and save a 5 second raw audio file:
107
107
 
108
108
  ```ruby
109
- microphone = Microphone.new
109
+ microphone = Pocketsphinx::Microphone.new
110
110
 
111
111
  File.open("test.raw", "wb") do |file|
112
112
  microphone.record do
@@ -130,7 +130,7 @@ To open this audio file take a look at [this wiki page](https://github.com/watso
130
130
  The `Decoder` class uses Pocketsphinx's libpocketsphinx to decode audio data into text. For example to decode a single utterance:
131
131
 
132
132
  ```ruby
133
- decoder = Decoder.new(Configuration.default)
133
+ decoder = Pocketsphinx::Decoder.new(Pocketsphinx::Configuration.default)
134
134
  decoder.decode 'spec/assets/audio/goforward.raw'
135
135
 
136
136
  puts decoder.hypothesis # => "go forward ten years"
@@ -142,16 +142,54 @@ puts decoder.hypothesis # => "go forward ten years"
142
142
  Keyword spotting is another feature that is not in the current stable (0.8) releases of Pocketsphinx, having been [merged into trunk](https://github.com/cmusphinx/pocketsphinx/commit/f562f9356cc7f1ade4941ebdde0c377642a023e3) early in 2014. In can be useful for detecting an activation keyword in a command and control application, while ignoring all other speech. Set up a recognizer as follows:
143
143
 
144
144
  ```ruby
145
- configuration = Configuration::KeywordSpotting.new('Okay computer')
146
- recognizer = LiveSpeechRecognizer.new(configuration)
145
+ configuration = Pocketsphinx::Configuration::KeywordSpotting.new('Okay computer')
146
+ recognizer = Pocketsphinx::LiveSpeechRecognizer.new(configuration)
147
147
  ```
148
148
 
149
- The `KeywordSpotting` configuration accepts a second argument for adjusting the sensitivity of the keyword detection. Note that this is just a wrapper which sets the `keyphrase` and `kws_threshold` settings on the default configuration.
149
+ The `KeywordSpotting` configuration accepts a second argument for adjusting the sensitivity of the keyword detection. Note that this is just a wrapper which sets the `keyphrase` and `kws_threshold` settings on the default configuration:
150
+
151
+ ```ruby
152
+ Pocketsphinx::Configuration::KeywordSpotting.new('keyword', 2).changes
153
+ # => [
154
+ # { :name => "keyphrase", :type => :string, :default => nil, :required => false, :value => "keyword", :info => "Keyphrase to spot" },
155
+ # { :name => "kws_threshold", :type => :float, :default => 1.0, :required => false, :value => 2.0, :info => "Threshold for p(hyp)/p(alternatives) ratio" },
156
+ # { :name => "lm", :type => :string, :default => "/usr/local/Cellar/cmu-pocketsphinx/HEAD/share/pocketsphinx/model/lm/en_US/hub4.5000.DMP", :required => false, :value => nil, :info => "Word trigram language model input file" }
157
+ # ]
158
+ ```
159
+
160
+
161
+ ### Grammars
162
+
163
+ Another way of configuring Pocketsphinx is with a grammar, which is normally used to describe very simple types of languages for command and control. Restricting the set of possible utterances in this way can greatly improve recognition accuracy for these types of application.
164
+
165
+ Load a [JSGF](http://www.w3.org/TR/jsgf/) grammar from a file:
166
+
167
+ ```ruby
168
+ configuration = Pocketsphinx::Configuration::Grammar.new('sentences.gram')
169
+ ```
170
+
171
+ Or build one dynamically with this simple DSL (currently only supports sentence lists):
172
+
173
+ ```ruby
174
+ configuration = Pocketsphinx::Configuration::Grammar.new do
175
+ sentence "Go forward ten meters"
176
+ sentence "Go backward ten meters"
177
+ end
178
+ ```
179
+
180
+
181
+ ## Troubleshooting
182
+
183
+ This gem has been tested with a manual Pocketsphinx installation on Ubuntu 14.04 and a Homebrew Pocketsphinx installation on OSX 10.9.4 Mavericks. Take a look at the following common problems before opening an issue.
184
+
185
+ **`attach_function': Function 'ps_default_search_args' not found in [libpocketsphinx.so] (FFI::NotFoundError)**
186
+
187
+ An error like this probably means that you have an old version of the Pocketsphinx libraries installed. If necessary, replace them with a recent development version which supports the features available in this gem.
150
188
 
151
189
 
152
190
  ## Contributing
153
191
 
154
- 1. Fork it ( https://github.com/[my-github-username]/pocketsphinx-ruby/fork )
192
+ 1. Fork it ( https://github.com/watsonbox/pocketsphinx-ruby/fork )
155
193
  2. Create your feature branch (`git checkout -b my-new-feature`)
156
194
  3. Commit your changes (`git commit -am 'Add some feature'`)
157
195
  4. Push to the branch (`git push origin my-new-feature`)
@@ -6,12 +6,18 @@ require "pocketsphinx/version"
6
6
  require "pocketsphinx/api/sphinxbase"
7
7
  require "pocketsphinx/api/sphinxad"
8
8
  require "pocketsphinx/api/pocketsphinx"
9
+ require "pocketsphinx/api/call_helpers"
10
+
11
+ # Grammar
12
+ require "pocketsphinx/grammar/jsgf"
13
+ require "pocketsphinx/grammar/jsgf_builder"
9
14
 
10
15
  # Configuration
11
- require 'pocketsphinx/configuration/setting_definition'
16
+ require "pocketsphinx/configuration/setting_definition"
12
17
  require "pocketsphinx/configuration/base"
13
18
  require "pocketsphinx/configuration/default"
14
19
  require "pocketsphinx/configuration/keyword_spotting"
20
+ require "pocketsphinx/configuration/grammar"
15
21
 
16
22
  require "pocketsphinx/audio_file"
17
23
  require "pocketsphinx/microphone"
@@ -0,0 +1,16 @@
1
+ module Pocketsphinx
2
+ module API
3
+ Error = Class.new(StandardError)
4
+
5
+ module CallHelpers
6
+ def api_call(method, *args)
7
+ calling_method = caller[0][/`.*'/][1..-2]
8
+ ps_api.send(method, *args).tap do |result|
9
+ if result < 0
10
+ raise Error, "#{self.class.to_s.split('::').last}##{calling_method} failed with error code #{result}"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -17,6 +17,10 @@ module Pocketsphinx
17
17
  attach_function :ps_end_utt, [:decoder], :int
18
18
  attach_function :ps_get_in_speech, [:decoder], :uint8
19
19
  attach_function :ps_get_hyp, [:decoder, :pointer, :pointer], :string
20
+ attach_function :ps_set_jsgf_string, [:decoder, :string, :string], :int
21
+ attach_function :ps_unset_search, [:decoder, :string], :int
22
+ attach_function :ps_get_search, [:decoder], :string
23
+ attach_function :ps_set_search, [:decoder, :string], :int
20
24
  end
21
25
  end
22
26
  end
@@ -7,6 +7,16 @@ module Pocketsphinx
7
7
  # Sets default grammar and language model if they are not set explicitly and
8
8
  # are present in the default search path.
9
9
  API::Pocketsphinx.ps_default_search_args(@ps_config)
10
+
11
+ # Treat ps_default_search_args settings as defaults
12
+ changes.each do |details|
13
+ setting_definitions[details[:name]].deflt = details[:value]
14
+ end
15
+ end
16
+
17
+ # Show details for settings which don't match Pocketsphinx defaults
18
+ def changes
19
+ details.reject { |d| d[:default] == d[:value] }
10
20
  end
11
21
  end
12
22
 
@@ -0,0 +1,21 @@
1
+ module Pocketsphinx
2
+ module Configuration
3
+ class Grammar < Default
4
+ attr_accessor :grammar
5
+
6
+ def initialize(*args, &block)#(grammar_path = nil)
7
+ super()
8
+
9
+ @grammar = ::Grammar::Jsgf.new(*args, &block)
10
+ end
11
+
12
+ # Since JSGF strings are not supported in Pocketsphinx configuration (only files),
13
+ # we use the post_init_decoder hook to configure the JSGF
14
+ def post_init_decoder(decoder)
15
+ decoder.unset_search
16
+ decoder.set_jsgf_string(grammar.raw)
17
+ decoder.set_search
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,6 @@
1
1
  module Pocketsphinx
2
2
  class Decoder < Struct.new(:configuration)
3
- Error = Class.new(StandardError)
3
+ include API::CallHelpers
4
4
 
5
5
  attr_writer :ps_api
6
6
 
@@ -13,10 +13,7 @@ module Pocketsphinx
13
13
  # nil, the previous configuration will be reloaded, with any changes applied.
14
14
  def reconfigure(configuration = nil)
15
15
  self.configuration = configuration if configuration
16
-
17
- ps_api.ps_reinit(ps_decoder, self.configuration.ps_config).tap do |result|
18
- raise Error, "Decoder#reconfigure failed with error code #{result}" if result < 0
19
- end
16
+ reinit_decoder
20
17
  end
21
18
 
22
19
  # Decode a raw audio stream as a single utterance, opening a file if path given
@@ -64,9 +61,7 @@ module Pocketsphinx
64
61
  # worth of data. This may allow the recognizer to produce more accurate results.
65
62
  # @return Number of frames of data searched
66
63
  def process_raw(buffer, size, no_search = false, full_utt = false)
67
- ps_api.ps_process_raw(ps_decoder, buffer, size, no_search ? 1 : 0, full_utt ? 1 : 0).tap do |result|
68
- raise Error, "Decoder#process_raw failed with error code #{result}" if result < 0
69
- end
64
+ api_call :ps_process_raw, ps_decoder, buffer, size, no_search ? 1 : 0, full_utt ? 1 : 0
70
65
  end
71
66
 
72
67
  # Start utterance processing.
@@ -77,16 +72,12 @@ module Pocketsphinx
77
72
  #
78
73
  # @param [String] name String uniquely identifying this utterance. If nil, one will be created.
79
74
  def start_utterance(name = nil)
80
- ps_api.ps_start_utt(ps_decoder, name).tap do |result|
81
- raise Error, "Decoder#start_utterance failed with error code #{result}" if result < 0
82
- end
75
+ api_call :ps_start_utt, ps_decoder, name
83
76
  end
84
77
 
85
78
  # End utterance processing
86
79
  def end_utterance
87
- ps_api.ps_end_utt(ps_decoder).tap do |result|
88
- raise Error, "Decoder#end_utterance failed with error code #{result}" if result < 0
89
- end
80
+ api_call :ps_end_utt, ps_decoder
90
81
  end
91
82
 
92
83
  # Checks if the last feed audio buffer contained speech
@@ -102,12 +93,64 @@ module Pocketsphinx
102
93
  ps_api.ps_get_hyp(ps_decoder, nil, nil)
103
94
  end
104
95
 
96
+ # Adds new search using JSGF model.
97
+ #
98
+ # Convenience method to parse JSGF model from string and create a search.
99
+ #
100
+ # @param [String] jsgf_string The JSGF grammar
101
+ # @param [String] name The search name
102
+ def set_jsgf_string(jsgf_string, name = 'default')
103
+ api_call :ps_set_jsgf_string, ps_decoder, name, jsgf_string
104
+ end
105
+
106
+ # Returns name of curent search in decoder
107
+ def get_search
108
+ ps_api.ps_get_search(ps_decoder)
109
+ end
110
+
111
+ # Actives search with the provided name.
112
+ #
113
+ # Activates search with the provided name. The search must be added before
114
+ # using either ps_set_fsg(), ps_set_lm() or ps_set_kws().
115
+ def set_search(name = 'default')
116
+ api_call :ps_set_search, ps_decoder, name
117
+ end
118
+
119
+ # Unsets the search and releases related resources.
120
+ #
121
+ # Unsets the search previously added with
122
+ # using either ps_set_fsg(), ps_set_lm() or ps_set_kws().
123
+ def unset_search(name = 'default')
124
+ api_call :ps_unset_search, ps_decoder, name
125
+ end
126
+
105
127
  def ps_api
106
128
  @ps_api || API::Pocketsphinx
107
129
  end
108
130
 
109
131
  def ps_decoder
110
- @ps_decoder ||= ps_api.ps_init(configuration.ps_config)
132
+ init_decoder if @ps_decoder.nil?
133
+ @ps_decoder
134
+ end
135
+
136
+ private
137
+
138
+ def init_decoder
139
+ @ps_decoder = ps_api.ps_init(configuration.ps_config)
140
+ post_init_decoder
141
+ end
142
+
143
+ def reinit_decoder
144
+ ps_api.ps_reinit(ps_decoder, configuration.ps_config).tap do |result|
145
+ raise API::Error, "Decoder#reconfigure failed with error code #{result}" if result < 0
146
+ post_init_decoder
147
+ end
148
+ end
149
+
150
+ def post_init_decoder
151
+ if configuration.respond_to?(:post_init_decoder)
152
+ configuration.post_init_decoder(self)
153
+ end
111
154
  end
112
155
  end
113
156
  end
@@ -0,0 +1,37 @@
1
+ module Pocketsphinx
2
+ module Grammar
3
+ class Jsgf
4
+ attr_reader :raw
5
+
6
+ def initialize(path = nil, &block)
7
+ if path.nil? && !block_given?
8
+ raise "Either a path or block is required to create a JSGF grammar"
9
+ end
10
+
11
+ if block_given?
12
+ @raw = grammar_from_block(&block)
13
+ else
14
+ @raw = grammar_from_file(path)
15
+ check_grammar
16
+ end
17
+ end
18
+
19
+ def grammar_from_file(path)
20
+ File.read path
21
+ end
22
+
23
+ def grammar_from_block(&block)
24
+ builder = JsgfBuilder.new
25
+ builder.instance_eval(&block)
26
+ builder.jsgf
27
+ end
28
+
29
+ private
30
+
31
+ def check_grammar
32
+ # Simple header check for now
33
+ raise 'Invalid JSGF grammar' unless raw.lines.first.strip == "#JSGF V1.0;"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ module Pocketsphinx
2
+ module Grammar
3
+ class JsgfBuilder
4
+ def initialize
5
+ @sentences = []
6
+ end
7
+
8
+ def sentence(sentence)
9
+ @sentences << sentence
10
+ end
11
+
12
+ def jsgf
13
+ header + sentences_rule
14
+ end
15
+
16
+ private
17
+
18
+ def header
19
+ "#JSGF V1.0;\n\ngrammar default;\n\n"
20
+ end
21
+
22
+ def sentences_rule
23
+ "public <sentence> = #{@sentences.map(&:downcase).join(' | ')};"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -3,7 +3,7 @@ module Pocketsphinx
3
3
  #
4
4
  # Implements Recordable interface (#record and #read_audio)
5
5
  class Microphone
6
- Error = Class.new(StandardError)
6
+ include API::CallHelpers
7
7
 
8
8
  attr_reader :ps_audio_device
9
9
  attr_writer :ps_api
@@ -36,15 +36,11 @@ module Pocketsphinx
36
36
  end
37
37
 
38
38
  def start_recording
39
- ps_api.ad_start_rec(@ps_audio_device).tap do |result|
40
- raise Error, "Microphone#start_recording failed with error code #{result}" if result < 0
41
- end
39
+ api_call :ad_start_rec, @ps_audio_device
42
40
  end
43
41
 
44
42
  def stop_recording
45
- ps_api.ad_stop_rec(@ps_audio_device).tap do |result|
46
- raise Error, "Microphone#stop_recording failed with error code #{result}" if result < 0
47
- end
43
+ api_call :ad_stop_rec, @ps_audio_device
48
44
  end
49
45
 
50
46
  # Read next block of audio samples while recording; read upto max samples into buf.
@@ -69,9 +65,7 @@ module Pocketsphinx
69
65
  end
70
66
 
71
67
  def close_device
72
- ps_api.ad_close(@ps_audio_device).tap do |result|
73
- raise Error, "Microphone#close_device failed with error code #{result}" if result < 0
74
- end
68
+ api_call :ad_close, @ps_audio_device
75
69
  end
76
70
 
77
71
  def ps_api
@@ -1,3 +1,3 @@
1
1
  module Pocketsphinx
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,15 @@
1
+ #JSGF V1.0;
2
+
3
+ /**
4
+ * JSGF Grammar for Turtle example
5
+ */
6
+
7
+ grammar goforward;
8
+
9
+ public <move> = go forward ten meters;
10
+
11
+ public <move2> = go <direction> <distance> [meter | meters];
12
+
13
+ <direction> = forward | backward;
14
+
15
+ <distance> = one | two | three | four | five | six | seven | eight | nine | ten;
@@ -0,0 +1 @@
1
+ This isn't a valid grammar
@@ -0,0 +1,5 @@
1
+ #JSGF V1.0;
2
+
3
+ grammar default;
4
+
5
+ public <sentence> = go forward ten meters | go backward ten meters;
@@ -90,12 +90,16 @@ describe Configuration do
90
90
  context 'keyword spotting configuration' do
91
91
  subject { Configuration::KeywordSpotting.new('Okay computer') }
92
92
 
93
- it 'sets the lowercase keyphrase' do
94
- expect(subject['keyphrase']).to eq('okay computer')
95
- end
93
+ it 'modifies the default configuration keyphrase and language model' do
94
+ changes = subject.changes
95
+
96
+ expect(changes.count).to be(2)
97
+
98
+ expect(changes[0][:name]).to eq('keyphrase')
99
+ expect(changes[0][:value]).to eq('okay computer')
96
100
 
97
- it 'uses no language model' do
98
- expect(subject['lm']).to be_nil
101
+ expect(changes[1][:name]).to eq('lm')
102
+ expect(changes[1][:value]).to be_nil
99
103
  end
100
104
 
101
105
  it 'exposes the keyphrase setting as #keyword' do
@@ -12,12 +12,18 @@ describe Decoder do
12
12
  end
13
13
 
14
14
  describe '#reconfigure' do
15
- it 'calls libpocketsphinx' do
15
+ it 'calls libpocketsphinx and the configuration post initialize hook' do
16
16
  expect(ps_api)
17
17
  .to receive(:ps_reinit)
18
18
  .with(subject.ps_decoder, configuration.ps_config)
19
19
  .and_return(0)
20
20
 
21
+ configuration.define_singleton_method(:post_init_decoder) { |decoder| }
22
+
23
+ expect(configuration)
24
+ .to receive(:post_init_decoder)
25
+ .with(subject)
26
+
21
27
  subject.reconfigure
22
28
  end
23
29
 
@@ -133,4 +139,74 @@ describe Decoder do
133
139
  expect(subject.hypothesis).to eq("Hypothesis")
134
140
  end
135
141
  end
142
+
143
+ describe '#set_jsgf_string' do
144
+ it 'calls libpocketsphinx' do
145
+ expect(ps_api)
146
+ .to receive(:ps_set_jsgf_string)
147
+ .with(subject.ps_decoder, 'default', 'JSGF')
148
+ .and_return(0)
149
+
150
+ subject.set_jsgf_string('JSGF')
151
+ end
152
+
153
+ it 'raises an exception on error' do
154
+ expect(ps_api)
155
+ .to receive(:ps_set_jsgf_string)
156
+ .and_return(-1)
157
+
158
+ expect { subject.set_jsgf_string('JSGF') }
159
+ .to raise_exception "Decoder#set_jsgf_string failed with error code -1"
160
+ end
161
+ end
162
+
163
+ describe '#set_search' do
164
+ it 'calls libpocketsphinx' do
165
+ expect(ps_api)
166
+ .to receive(:ps_set_search)
167
+ .with(subject.ps_decoder, 'search')
168
+ .and_return(0)
169
+
170
+ subject.set_search('search')
171
+ end
172
+
173
+ it 'raises an exception on error' do
174
+ expect(ps_api)
175
+ .to receive(:ps_set_search)
176
+ .and_return(-1)
177
+
178
+ expect { subject.set_search('search') }
179
+ .to raise_exception "Decoder#set_search failed with error code -1"
180
+ end
181
+ end
182
+
183
+ describe '#unset_search' do
184
+ it 'calls libpocketsphinx' do
185
+ expect(ps_api)
186
+ .to receive(:ps_unset_search)
187
+ .with(subject.ps_decoder, 'search')
188
+ .and_return(0)
189
+
190
+ subject.unset_search('search')
191
+ end
192
+
193
+ it 'raises an exception on error' do
194
+ expect(ps_api)
195
+ .to receive(:ps_unset_search)
196
+ .and_return(-1)
197
+
198
+ expect { subject.unset_search('search') }
199
+ .to raise_exception "Decoder#unset_search failed with error code -1"
200
+ end
201
+ end
202
+
203
+ describe '#get_search' do
204
+ it 'calls libpocketsphinx' do
205
+ expect(ps_api)
206
+ .to receive(:ps_get_search)
207
+ .and_return(:search)
208
+
209
+ expect(subject.get_search).to eq(:search)
210
+ end
211
+ end
136
212
  end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grammar::Jsgf do
4
+ it "raises an exception when neither a file or block are given" do
5
+ expect { Grammar::Jsgf.new }.to raise_exception "Either a path or block is required to create a JSGF grammar"
6
+ end
7
+
8
+ context "reading a grammar from a file" do
9
+ let(:grammar_path) { grammar :goforward }
10
+ subject { Grammar::Jsgf.new(grammar_path) }
11
+
12
+ it "reads a grammar from a file" do
13
+ expect(subject.raw.lines.count).to eq(15)
14
+ end
15
+
16
+ context "the grammar file is invalid" do
17
+ let(:grammar_path) { grammar :invalid }
18
+
19
+ it "raises an exception" do
20
+ expect { subject }.to raise_exception "Invalid JSGF grammar"
21
+ end
22
+ end
23
+ end
24
+
25
+ context "building a grammer from a block" do
26
+ subject do
27
+ Grammar::Jsgf.new do
28
+ sentence "Go forward ten meters"
29
+ sentence "Go backward ten meters"
30
+ end
31
+ end
32
+
33
+ it "builds a grammar from a block" do
34
+ expect(subject.raw).to eq(File.read grammar(:sentences))
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def grammar(name)
41
+ "spec/assets/grammars/#{name}.gram"
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'speech recognition with default configuration' do
4
+ subject do
5
+ AudioFileSpeechRecognizer.new.tap do |speech_recognizer|
6
+ speech_recognizer.decoder = @decoder
7
+ end
8
+ end
9
+
10
+ # Share decoder across all examples for speed
11
+ before :all do
12
+ @decoder = Decoder.new(Configuration.default)
13
+ end
14
+
15
+ describe '#recognize' do
16
+ it 'should decode speech in raw audio' do
17
+ expect { |b| subject.recognize('spec/assets/audio/goforward.raw', 4096, &b) }.
18
+ to yield_with_args("go forward ten years")
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe SpeechRecognizer do
3
+ describe 'speech recognition with a grammar' do
4
4
  let(:recordable) { AudioFile.new('spec/assets/audio/goforward.raw') }
5
5
 
6
6
  subject do
@@ -12,12 +12,13 @@ describe SpeechRecognizer do
12
12
 
13
13
  # Share decoder across all examples for speed
14
14
  before :all do
15
- @decoder = Decoder.new(Configuration.default)
15
+ @configuration = Configuration::Grammar.new('spec/assets/grammars/goforward.gram')
16
+ @decoder = Decoder.new(@configuration)
16
17
  end
17
18
 
18
19
  describe '#recognize' do
19
20
  it 'should decode speech in raw audio' do
20
- expect { |b| subject.recognize(4096, &b) }.to yield_with_args("go forward ten years")
21
+ expect { |b| subject.recognize(4096, &b) }.to yield_with_args("go forward ten meters")
21
22
  end
22
23
  end
23
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pocketsphinx-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Howard Wilson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-21 00:00:00.000000000 Z
11
+ date: 2014-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -100,6 +100,7 @@ files:
100
100
  - examples/record_audio_file.rb
101
101
  - lib/pocketsphinx-ruby.rb
102
102
  - lib/pocketsphinx.rb
103
+ - lib/pocketsphinx/api/call_helpers.rb
103
104
  - lib/pocketsphinx/api/pocketsphinx.rb
104
105
  - lib/pocketsphinx/api/sphinxad.rb
105
106
  - lib/pocketsphinx/api/sphinxbase.rb
@@ -107,19 +108,27 @@ files:
107
108
  - lib/pocketsphinx/audio_file_speech_recognizer.rb
108
109
  - lib/pocketsphinx/configuration/base.rb
109
110
  - lib/pocketsphinx/configuration/default.rb
111
+ - lib/pocketsphinx/configuration/grammar.rb
110
112
  - lib/pocketsphinx/configuration/keyword_spotting.rb
111
113
  - lib/pocketsphinx/configuration/setting_definition.rb
112
114
  - lib/pocketsphinx/decoder.rb
115
+ - lib/pocketsphinx/grammar/jsgf.rb
116
+ - lib/pocketsphinx/grammar/jsgf_builder.rb
113
117
  - lib/pocketsphinx/live_speech_recognizer.rb
114
118
  - lib/pocketsphinx/microphone.rb
115
119
  - lib/pocketsphinx/speech_recognizer.rb
116
120
  - lib/pocketsphinx/version.rb
117
121
  - pocketsphinx-ruby.gemspec
118
122
  - spec/assets/audio/goforward.raw
123
+ - spec/assets/grammars/goforward.gram
124
+ - spec/assets/grammars/invalid.gram
125
+ - spec/assets/grammars/sentences.gram
119
126
  - spec/configuration_spec.rb
120
127
  - spec/decoder_spec.rb
128
+ - spec/grammar_spec.rb
121
129
  - spec/integration/decoder_spec.rb
122
- - spec/integration/speech_recognizer_spec.rb
130
+ - spec/integration/default_recognition_spec.rb
131
+ - spec/integration/grammar_recognition_spec.rb
123
132
  - spec/microphone_spec.rb
124
133
  - spec/spec_helper.rb
125
134
  - spec/speech_recognizer_spec.rb
@@ -149,10 +158,15 @@ specification_version: 4
149
158
  summary: Ruby FFI pocketsphinx bindings
150
159
  test_files:
151
160
  - spec/assets/audio/goforward.raw
161
+ - spec/assets/grammars/goforward.gram
162
+ - spec/assets/grammars/invalid.gram
163
+ - spec/assets/grammars/sentences.gram
152
164
  - spec/configuration_spec.rb
153
165
  - spec/decoder_spec.rb
166
+ - spec/grammar_spec.rb
154
167
  - spec/integration/decoder_spec.rb
155
- - spec/integration/speech_recognizer_spec.rb
168
+ - spec/integration/default_recognition_spec.rb
169
+ - spec/integration/grammar_recognition_spec.rb
156
170
  - spec/microphone_spec.rb
157
171
  - spec/spec_helper.rb
158
172
  - spec/speech_recognizer_spec.rb