pocketsphinx-ruby 0.1.0 → 0.1.1

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: d3479a20de1bf075e2a4d2efcf8721c05a650751
4
- data.tar.gz: a3ea68aaf9e0dc60149c2992dd8316233d8568f3
3
+ metadata.gz: 0129cb6b05e984d481f79c27fd085cb119eb195f
4
+ data.tar.gz: 9a6e6c3750992d6a1d3c7b8d80005b03e7d01b5c
5
5
  SHA512:
6
- metadata.gz: e732d04275721ed223776c7d90b97894e8a778e73e334a036561715efbf868b65e8b20809730013fcaf020f21ab5de2fa646af6b7bc7aeb2f467345b6492f33e
7
- data.tar.gz: a6670826d281b272ea29d4d609805328d2da8af4753d66349e78f222c5c99eaf05a7dde19faad8ac070b57e03aacab20396c5686c8b7365e4d586591bc958add
6
+ metadata.gz: ef774d606a2c53df8c88e42fb9593cada5347993feb0bf7b044362faf8b5ba28cc8728674732125bef1cd7b7cc78ee8a9ed81d092c4d08b626758e6d93929754
7
+ data.tar.gz: 656a27d5578fc665116afaa1b63a76ae81e7616cf6f1af49fa65dffca6f01a5e9e5941df2a6b6e9ac825c48e9b9854e77d70cf0eae4b4011b24a5fed3baa4dc1
data/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ **v0.1.1 - 29/10/14**
4
+
5
+ * Allow logging to be disabled
6
+ * Recognizer can now be paused (during TTS reply for example)
7
+ * Spot keywords immediately by not using speech -> silence transitions
8
+ * Return path_score and utterance_id with hypothesis
9
+ * Fix namespacing bug in Configuration::Grammar
10
+ * Improve test coverage
11
+
12
+
13
+ **v0.1.0 - 24/10/14**
14
+
15
+ * Support for JSGF grammars + very simple sentences DSL
16
+
17
+
18
+ **v0.0.3 - 21/10/14**
19
+
20
+ * Support for keyword spotting configuration
21
+ * Support reconfiguring of Decoder / Recognizer
22
+ * Fix CPU usage bug in `Microphone#read_audio_delay`
23
+ * Fix bug in `Configuration` float value type checking
24
+
25
+
26
+ **v0.0.2 - 20/10/14**
27
+
28
+ * Support for decoding raw audio files as well as live audio
29
+
30
+
31
+ **v0.0.1**
32
+
33
+ Initial release
data/lib/pocketsphinx.rb CHANGED
@@ -27,5 +27,7 @@ require "pocketsphinx/live_speech_recognizer"
27
27
  require "pocketsphinx/audio_file_speech_recognizer"
28
28
 
29
29
  module Pocketsphinx
30
-
30
+ def self.disable_logging
31
+ API::Sphinxbase.err_set_logfp(nil)
32
+ end
31
33
  end
@@ -21,6 +21,7 @@ module Pocketsphinx
21
21
  attach_function :cmd_ln_set_str_r, [:pointer, :string, :string], :void
22
22
  attach_function :err_set_debug_level, [:int], :int
23
23
  attach_function :err_set_logfile, [:string], :int
24
+ attach_function :err_set_logfp, [:pointer], :void
24
25
  end
25
26
  end
26
27
  end
@@ -1,14 +1,6 @@
1
1
  module Pocketsphinx
2
- # Implements Recordable interface (#record and #read_audio)
2
+ # Implements Recordable interface (#start_recording, #stop_recording and #read_audio)
3
3
  class AudioFile < Struct.new(:file_path)
4
- def record
5
- File.open(file_path, 'rb') do |file|
6
- self.file = file
7
- yield
8
- self.file = nil
9
- end
10
- end
11
-
12
4
  # Read next block of audio samples from file; up to max samples into buffer.
13
5
  #
14
6
  # @param [FFI::Pointer] buffer 16bit buffer of at least max_samples in size
@@ -16,7 +8,7 @@ module Pocketsphinx
16
8
  # @return [Fixnum] Samples actually read; nil if EOF
17
9
  def read_audio(buffer, max_samples = 4096)
18
10
  if file.nil?
19
- raise "Can't read audio: use AudioFile#record to open the file first"
11
+ raise "Can't read audio: use AudioFile#start_recording to open the file first"
20
12
  end
21
13
 
22
14
  if data = file.read(max_samples * 2)
@@ -25,6 +17,17 @@ module Pocketsphinx
25
17
  end
26
18
  end
27
19
 
20
+ def start_recording
21
+ self.file = File.open(file_path, 'rb')
22
+ end
23
+
24
+ def stop_recording
25
+ if file
26
+ file.close
27
+ self.file = nil
28
+ end
29
+ end
30
+
28
31
  private
29
32
 
30
33
  attr_accessor :file
@@ -48,7 +48,7 @@ module Pocketsphinx
48
48
  when :boolean
49
49
  API::Sphinxbase.cmd_ln_int_r(ps_config, "-#{name}") != 0
50
50
  when :string_list
51
- raise NotImplementedException
51
+ raise NotImplementedError
52
52
  end
53
53
  end
54
54
 
@@ -66,7 +66,7 @@ module Pocketsphinx
66
66
  when :boolean
67
67
  API::Sphinxbase.cmd_ln_set_int_r(ps_config, "-#{name}", value ? 1 : 0)
68
68
  when :string_list
69
- raise NotImplementedException
69
+ raise NotImplementedError
70
70
  end
71
71
  end
72
72
 
@@ -6,7 +6,7 @@ module Pocketsphinx
6
6
  def initialize(*args, &block)#(grammar_path = nil)
7
7
  super()
8
8
 
9
- @grammar = ::Grammar::Jsgf.new(*args, &block)
9
+ @grammar = Pocketsphinx::Grammar::Jsgf.new(*args, &block)
10
10
  end
11
11
 
12
12
  # Since JSGF strings are not supported in Pocketsphinx configuration (only files),
@@ -27,6 +27,11 @@ module Pocketsphinx
27
27
  self['kws_threshold'] = value
28
28
  end
29
29
 
30
+ # See SpeechRecognizer#algorithm
31
+ def recognition_algorithm
32
+ :continuous
33
+ end
34
+
30
35
  private
31
36
 
32
37
  def sanitize_keyword(keyword)
@@ -1,7 +1,18 @@
1
1
  module Pocketsphinx
2
2
  class Decoder < Struct.new(:configuration)
3
+ require 'delegate'
4
+
3
5
  include API::CallHelpers
4
6
 
7
+ class Hypothesis < SimpleDelegator
8
+ attr_accessor :path_score, :utterance_id
9
+
10
+ def initialize(string, path_score, utterance_id)
11
+ @path_score, @utterance_id = path_score, utterance_id
12
+ super(string)
13
+ end
14
+ end
15
+
5
16
  attr_writer :ps_api
6
17
 
7
18
  # Reinitialize the decoder with updated configuration.
@@ -85,12 +96,20 @@ module Pocketsphinx
85
96
  ps_api.ps_get_in_speech(ps_decoder) != 0
86
97
  end
87
98
 
88
- # Get hypothesis string and path score.
99
+ # Get hypothesis string (with #path_score and #utterance_id).
89
100
  #
90
- # @return [String] Hypothesis string
91
- # @todo Expand to return path score and utterance ID
101
+ # @return [Hypothesis] Hypothesis (behaves like a string)
92
102
  def hypothesis
93
- ps_api.ps_get_hyp(ps_decoder, nil, nil)
103
+ mp_path_score = FFI::MemoryPointer.new(:int32, 1)
104
+ mp_utterance_id = FFI::MemoryPointer.new(:pointer, 1)
105
+
106
+ hypothesis = ps_api.ps_get_hyp(ps_decoder, mp_path_score, mp_utterance_id)
107
+
108
+ hypothesis.nil? ? nil : Hypothesis.new(
109
+ hypothesis,
110
+ mp_path_score.get_int32(0),
111
+ mp_utterance_id.read_pointer.read_string.force_encoding('UTF-8')
112
+ )
94
113
  end
95
114
 
96
115
  # Adds new search using JSGF model.
@@ -1,7 +1,7 @@
1
1
  module Pocketsphinx
2
2
  # Provides non-blocking live audio recording using libsphinxad
3
3
  #
4
- # Implements Recordable interface (#record and #read_audio)
4
+ # Implements Recordable interface (#start_recording, #stop_recording and #read_audio)
5
5
  class Microphone
6
6
  include API::CallHelpers
7
7
 
@@ -3,11 +3,13 @@ module Pocketsphinx
3
3
  #
4
4
  # Essentially orchestrates interaction between Recordable and Decoder, and detects new utterances.
5
5
  class SpeechRecognizer
6
- # Recordable interface must implement #record and #read_audio
6
+ # Recordable interface must implement #start_recording, #stop_recording and #read_audio
7
7
  attr_writer :recordable
8
8
  attr_writer :decoder
9
9
  attr_writer :configuration
10
10
 
11
+ ALGORITHMS = [:after_speech, :continuous]
12
+
11
13
  def initialize(configuration = nil)
12
14
  @configuration = configuration
13
15
  end
@@ -33,39 +35,28 @@ module Pocketsphinx
33
35
  def reconfigure(configuration = nil)
34
36
  self.configuration = configuration if configuration
35
37
 
36
- decoder.reconfigure(configuration)
37
- decoder.start_utterance if recognizing?
38
+ pause do
39
+ decoder.reconfigure(configuration)
40
+ end
38
41
  end
39
42
 
40
- # Recognize utterances and yield hypotheses in infinite loop
41
- #
42
- # Splits speech into utterances by detecting silence between them.
43
- # By default this uses Pocketsphinx's internal Voice Activity Detection (VAD) which can be
44
- # configured by adjusting the `vad_postspeech`, `vad_prespeech`, and `vad_threshold` settings.
43
+ # Recognize speech and yield hypotheses in infinite loop
45
44
  #
46
45
  # @param [Fixnum] max_samples Number of samples to process at a time
47
- def recognize(max_samples = 4096)
48
- decoder.start_utterance
49
- @recognizing = true
46
+ def recognize(max_samples = 4096, &b)
47
+ unless ALGORITHMS.include?(algorithm)
48
+ raise NotImplementedError, "Unknown speech recognition algorithm: #{algorithm}"
49
+ end
50
50
 
51
- recordable.record do
52
- FFI::MemoryPointer.new(:int16, max_samples) do |buffer|
53
- loop do
54
- if in_speech?
55
- while decoder.in_speech?
56
- process_audio(buffer, max_samples) or break
57
- end
58
-
59
- hypothesis = get_hypothesis
60
- yield hypothesis if hypothesis
61
- else
62
- process_audio(buffer, max_samples) or break
63
- end
64
- end
51
+ start unless recognizing?
52
+
53
+ FFI::MemoryPointer.new(:int16, max_samples) do |buffer|
54
+ loop do
55
+ send("recognize_#{algorithm}", max_samples, buffer, &b) or break
65
56
  end
66
57
  end
67
58
  ensure
68
- @recognizing = false
59
+ stop
69
60
  end
70
61
 
71
62
  def in_speech?
@@ -77,8 +68,73 @@ module Pocketsphinx
77
68
  @recognizing == true
78
69
  end
79
70
 
71
+ def pause
72
+ recognizing?.tap do |was_recognizing|
73
+ stop if was_recognizing
74
+ yield
75
+ start if was_recognizing
76
+ end
77
+ end
78
+
79
+ def start
80
+ recordable.start_recording
81
+ decoder.start_utterance
82
+ @recognizing = true
83
+ end
84
+
85
+ def stop
86
+ decoder.end_utterance
87
+ recordable.stop_recording
88
+ @recognizing = false
89
+ end
90
+
91
+ # Determine which algorithm to use for co-ordinating speech recognition
92
+ #
93
+ # @return [Symbol] :continuous or :after_speech
94
+ # :continuous yields as soon as any hypothesis is available
95
+ # :after_speech yields hypothesis on speech -> silence transition if one exists
96
+ # Default is :after_speech
97
+ def algorithm
98
+ if configuration.respond_to?(:recognition_algorithm)
99
+ configuration.recognition_algorithm
100
+ else
101
+ ALGORITHMS.first
102
+ end
103
+ end
104
+
80
105
  private
81
106
 
107
+ # Yields as soon as any hypothesis is available
108
+ def recognize_continuous(max_samples, buffer)
109
+ process_audio(buffer, max_samples).tap do
110
+ if hypothesis = decoder.hypothesis
111
+ yield hypothesis
112
+
113
+ decoder.end_utterance
114
+ decoder.start_utterance
115
+ end
116
+ end
117
+ end
118
+
119
+ # Splits speech into utterances by detecting silence between them.
120
+ # By default this uses Pocketsphinx's internal Voice Activity Detection (VAD) which can be
121
+ # configured by adjusting the `vad_postspeech`, `vad_prespeech`, and `vad_threshold` settings.
122
+ def recognize_after_speech(max_samples, buffer)
123
+ if in_speech?
124
+ while in_speech?
125
+ process_audio(buffer, max_samples) or break
126
+ end
127
+
128
+ decoder.end_utterance
129
+ hypothesis = decoder.hypothesis
130
+ decoder.start_utterance
131
+
132
+ yield hypothesis if hypothesis
133
+ end
134
+
135
+ process_audio(buffer, max_samples)
136
+ end
137
+
82
138
  def process_audio(buffer, max_samples)
83
139
  sample_count = recordable.read_audio(buffer, max_samples)
84
140
 
@@ -93,13 +149,5 @@ module Pocketsphinx
93
149
 
94
150
  sample_count
95
151
  end
96
-
97
- # Called on speech -> silence transition
98
- def get_hypothesis
99
- decoder.end_utterance
100
- decoder.hypothesis.tap do
101
- decoder.start_utterance
102
- end
103
- end
104
152
  end
105
153
  end
@@ -1,3 +1,3 @@
1
1
  module Pocketsphinx
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Pocketsphinx::VERSION
9
9
  spec.authors = ["Howard Wilson"]
10
10
  spec.email = ["howard@watsonbox.net"]
11
- spec.summary = %q{Ruby FFI pocketsphinx bindings}
12
- spec.description = %q{Ruby FFI pocketsphinx bindings}
11
+ spec.summary = %q{Ruby speech recognition with Pocketsphinx}
12
+ spec.description = %q{Provides Ruby FFI bindings for Pocketsphinx, a lightweight speech recognition engine.}
13
13
  spec.homepage = "https://github.com/watsonbox/pocketsphinx-ruby"
14
14
  spec.license = "MIT"
15
15
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Configuration do
3
+ describe Pocketsphinx::Configuration do
4
4
  subject { Pocketsphinx::Configuration.default }
5
5
 
6
6
  it "provides a default pocketsphinx configuration" do
@@ -46,6 +46,15 @@ describe Configuration do
46
46
  expect { subject['smoothspec'] = nil }.to raise_exception "Only string settings can be set to nil"
47
47
  end
48
48
 
49
+ it "does not support string lists" do
50
+ subject.setting_definitions['string_list_setting'] = Pocketsphinx::Configuration::SettingDefinition.new(
51
+ 'string_list_setting', 32, nil, nil
52
+ )
53
+
54
+ expect { subject['string_list_setting'] }.to raise_exception NotImplementedError
55
+ expect { subject['string_list_setting'] = 'value' }.to raise_exception NotImplementedError
56
+ end
57
+
49
58
  it 'raises exceptions when setting with incorrectly typed values' do
50
59
  expect { subject['frate'] = true }.to raise_exception "Configuration setting 'frate' must be of type Integer"
51
60
  end
@@ -88,7 +97,7 @@ describe Configuration do
88
97
  end
89
98
 
90
99
  context 'keyword spotting configuration' do
91
- subject { Configuration::KeywordSpotting.new('Okay computer') }
100
+ subject { Pocketsphinx::Configuration::KeywordSpotting.new('Okay computer') }
92
101
 
93
102
  it 'modifies the default configuration keyphrase and language model' do
94
103
  changes = subject.changes
data/spec/decoder_spec.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Decoder do
4
- subject { Decoder.new(configuration) }
3
+ describe Pocketsphinx::Decoder do
4
+ subject { Pocketsphinx::Decoder.new(configuration) }
5
5
  let(:ps_api) { subject.ps_api }
6
6
  let(:ps_decoder) { double }
7
- let(:configuration) { Configuration.default }
7
+ let(:configuration) { Pocketsphinx::Configuration.default }
8
8
 
9
9
  before do
10
10
  subject.ps_api = double
@@ -132,11 +132,22 @@ describe Decoder do
132
132
  describe '#hypothesis' do
133
133
  it 'calls libpocketsphinx' do
134
134
  expect(ps_api)
135
- .to receive(:ps_get_hyp)
136
- .with(subject.ps_decoder, nil, nil)
137
- .and_return("Hypothesis")
135
+ .to receive(:ps_get_hyp) do |ps_decoder, mp_path_score, mp_utterance_id|
136
+ expect(ps_decoder).to eq(subject.ps_decoder)
137
+ expect(mp_path_score).to be_a(FFI::MemoryPointer)
138
+ expect(mp_utterance_id).to be_a(FFI::MemoryPointer)
138
139
 
139
- expect(subject.hypothesis).to eq("Hypothesis")
140
+ mp_path_score.put_int32(0, 20)
141
+ mp_utterance_id.write_pointer(FFI::MemoryPointer.from_string("Utterance"))
142
+
143
+ "Hypothesis"
144
+ end
145
+
146
+ hypothesis = subject.hypothesis
147
+
148
+ expect(hypothesis).to eq("Hypothesis")
149
+ expect(hypothesis.path_score).to eq(20)
150
+ expect(hypothesis.utterance_id).to eq("Utterance")
140
151
  end
141
152
  end
142
153
 
data/spec/grammar_spec.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Grammar::Jsgf do
3
+ describe Pocketsphinx::Grammar::Jsgf do
4
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"
5
+ expect { Pocketsphinx::Grammar::Jsgf.new }.to raise_exception "Either a path or block is required to create a JSGF grammar"
6
6
  end
7
7
 
8
8
  context "reading a grammar from a file" do
9
9
  let(:grammar_path) { grammar :goforward }
10
- subject { Grammar::Jsgf.new(grammar_path) }
10
+ subject { Pocketsphinx::Grammar::Jsgf.new(grammar_path) }
11
11
 
12
12
  it "reads a grammar from a file" do
13
13
  expect(subject.raw.lines.count).to eq(15)
@@ -24,7 +24,7 @@ describe Grammar::Jsgf do
24
24
 
25
25
  context "building a grammer from a block" do
26
26
  subject do
27
- Grammar::Jsgf.new do
27
+ Pocketsphinx::Grammar::Jsgf.new do
28
28
  sentence "Go forward ten meters"
29
29
  sentence "Go backward ten meters"
30
30
  end
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Decoder do
3
+ describe Pocketsphinx::Decoder do
4
4
  subject { @decoder }
5
5
  let(:configuration) { @configuration }
6
6
 
7
7
  # Share decoder across all examples for speed
8
8
  before :all do
9
- @configuration = Configuration.default
10
- @decoder = Decoder.new(@configuration)
9
+ @configuration = Pocketsphinx::Configuration.default
10
+ @decoder = Pocketsphinx::Decoder.new(@configuration)
11
11
  end
12
12
 
13
13
  describe '#decode' do
@@ -2,14 +2,14 @@ require 'spec_helper'
2
2
 
3
3
  describe 'speech recognition with default configuration' do
4
4
  subject do
5
- AudioFileSpeechRecognizer.new.tap do |speech_recognizer|
5
+ Pocketsphinx::AudioFileSpeechRecognizer.new.tap do |speech_recognizer|
6
6
  speech_recognizer.decoder = @decoder
7
7
  end
8
8
  end
9
9
 
10
10
  # Share decoder across all examples for speed
11
11
  before :all do
12
- @decoder = Decoder.new(Configuration.default)
12
+ @decoder = Pocketsphinx::Decoder.new(Pocketsphinx::Configuration.default)
13
13
  end
14
14
 
15
15
  describe '#recognize' do
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'speech recognition with a grammar' do
4
- let(:recordable) { AudioFile.new('spec/assets/audio/goforward.raw') }
4
+ let(:recordable) { Pocketsphinx::AudioFile.new('spec/assets/audio/goforward.raw') }
5
5
 
6
6
  subject do
7
- SpeechRecognizer.new.tap do |speech_recognizer|
7
+ Pocketsphinx::SpeechRecognizer.new(@configuration).tap do |speech_recognizer|
8
8
  speech_recognizer.recordable = recordable
9
9
  speech_recognizer.decoder = @decoder
10
10
  end
@@ -12,8 +12,8 @@ describe 'speech recognition with a grammar' do
12
12
 
13
13
  # Share decoder across all examples for speed
14
14
  before :all do
15
- @configuration = Configuration::Grammar.new('spec/assets/grammars/goforward.gram')
16
- @decoder = Decoder.new(@configuration)
15
+ @configuration = Pocketsphinx::Configuration::Grammar.new('spec/assets/grammars/goforward.gram')
16
+ @decoder = Pocketsphinx::Decoder.new(@configuration)
17
17
  end
18
18
 
19
19
  describe '#recognize' do
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ # Keyword spotting recognizes keywords mid-speech, not only after a speech -> silence transition
4
+ describe 'keyword spotting' do
5
+ let(:recordable) { Pocketsphinx::AudioFile.new('spec/assets/audio/goforward.raw') }
6
+
7
+ subject do
8
+ Pocketsphinx::SpeechRecognizer.new(@configuration).tap do |speech_recognizer|
9
+ speech_recognizer.recordable = recordable
10
+ speech_recognizer.decoder = @decoder
11
+ end
12
+ end
13
+
14
+ # Share decoder across all examples for speed
15
+ before :all do
16
+ @configuration = Pocketsphinx::Configuration::KeywordSpotting.new('forward')
17
+ @decoder = Pocketsphinx::Decoder.new(@configuration)
18
+ end
19
+
20
+ describe '#recognize' do
21
+ it 'should decode speech in raw audio' do
22
+ expect { |b| subject.recognize(4096, &b) }.to yield_with_args('forward')
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Pocketsphinx::LiveSpeechRecognizer do
4
+ it 'uses the microphone for audio input' do
5
+ expect(Pocketsphinx::Microphone).to receive(:new).and_return(:microphone)
6
+ expect(Pocketsphinx::LiveSpeechRecognizer.new.recordable).to eq(:microphone)
7
+ end
8
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Microphone do
3
+ describe Pocketsphinx::Microphone do
4
4
  module DummyAPI
5
5
  def self.ad_open_dev(default_device, sample_rate)
6
6
  :audio_device
@@ -13,7 +13,7 @@ describe Microphone do
13
13
  # Share microphone across all examples for speed
14
14
  before :all do
15
15
  # Don't open an audio device as there isn't one on Travis CI
16
- @microphone = Microphone.new(16000, nil, DummyAPI)
16
+ @microphone = Pocketsphinx::Microphone.new(16000, nil, DummyAPI)
17
17
  end
18
18
 
19
19
  describe '#start_recording' do
data/spec/spec_helper.rb CHANGED
@@ -11,8 +11,6 @@ FileUtils.touch POCKETSPHINX_LOG_FILE
11
11
  Pocketsphinx::API::Sphinxbase.err_set_logfile POCKETSPHINX_LOG_FILE
12
12
 
13
13
  RSpec.configure do |config|
14
- include Pocketsphinx
15
-
16
14
  # rspec-expectations config goes here. You can use an alternate
17
15
  # assertion/expectation library such as wrong or the stdlib/minitest
18
16
  # assertions if you prefer.
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe SpeechRecognizer do
3
+ describe Pocketsphinx::SpeechRecognizer do
4
4
  let(:configuration) { double }
5
5
  let(:recordable) { double }
6
6
  let(:decoder) { double }
7
- subject { SpeechRecognizer.new(configuration) }
7
+ subject { Pocketsphinx::SpeechRecognizer.new(configuration) }
8
8
 
9
9
  before do
10
10
  subject.decoder = decoder
@@ -30,9 +30,13 @@ describe SpeechRecognizer do
30
30
  subject.reconfigure(:new_configuration)
31
31
  end
32
32
 
33
- it 'restarts an utterance if recognition was interrupted' do
34
- expect(subject).to receive(:recognizing?).and_return(true)
35
- expect(decoder).to receive(:start_utterance)
33
+ it 'restarts recognition if it was interrupted' do
34
+ allow(subject).to receive(:recognizing?).and_return(true)
35
+
36
+ expect(decoder).to receive(:end_utterance).ordered
37
+ expect(recordable).to receive(:stop_recording).ordered
38
+ expect(recordable).to receive(:start_recording).ordered
39
+ expect(decoder).to receive(:start_utterance).ordered
36
40
 
37
41
  subject.reconfigure
38
42
  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.1.0
4
+ version: 0.1.1
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-24 00:00:00.000000000 Z
11
+ date: 2014-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -80,7 +80,8 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- description: Ruby FFI pocketsphinx bindings
83
+ description: Provides Ruby FFI bindings for Pocketsphinx, a lightweight speech recognition
84
+ engine.
84
85
  email:
85
86
  - howard@watsonbox.net
86
87
  executables: []
@@ -90,6 +91,7 @@ files:
90
91
  - ".gitignore"
91
92
  - ".rspec"
92
93
  - ".travis.yml"
94
+ - CHANGELOG.md
93
95
  - Gemfile
94
96
  - LICENSE.txt
95
97
  - README.md
@@ -129,6 +131,8 @@ files:
129
131
  - spec/integration/decoder_spec.rb
130
132
  - spec/integration/default_recognition_spec.rb
131
133
  - spec/integration/grammar_recognition_spec.rb
134
+ - spec/integration/keyword_recognition_spec.rb
135
+ - spec/live_speech_recognizer_spec.rb
132
136
  - spec/microphone_spec.rb
133
137
  - spec/spec_helper.rb
134
138
  - spec/speech_recognizer_spec.rb
@@ -155,7 +159,7 @@ rubyforge_project:
155
159
  rubygems_version: 2.2.2
156
160
  signing_key:
157
161
  specification_version: 4
158
- summary: Ruby FFI pocketsphinx bindings
162
+ summary: Ruby speech recognition with Pocketsphinx
159
163
  test_files:
160
164
  - spec/assets/audio/goforward.raw
161
165
  - spec/assets/grammars/goforward.gram
@@ -167,6 +171,8 @@ test_files:
167
171
  - spec/integration/decoder_spec.rb
168
172
  - spec/integration/default_recognition_spec.rb
169
173
  - spec/integration/grammar_recognition_spec.rb
174
+ - spec/integration/keyword_recognition_spec.rb
175
+ - spec/live_speech_recognizer_spec.rb
170
176
  - spec/microphone_spec.rb
171
177
  - spec/spec_helper.rb
172
178
  - spec/speech_recognizer_spec.rb