pocketsphinx-ruby 0.1.0 → 0.1.1

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: 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