test_rhino.py
Go to the documentation of this file.
1 #
2 # Copyright 2018-2022 Picovoice Inc.
3 #
4 # You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
5 # file accompanying this source.
6 #
7 # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8 # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 # specific language governing permissions and limitations under the License.
10 #
11 
12 import struct
13 import sys
14 import unittest
15 import wave
16 
17 from rhino import Rhino
18 from util import *
19 
20 
21 class RhinoTestCase(unittest.TestCase):
22  @staticmethod
23  def __append_language(s, language):
24  if language == 'en':
25  return s
26  return '%s_%s' % (s, language)
27 
28  @staticmethod
29  def __read_file(file_name, sample_rate):
30  wav_file = wave.open(file_name, mode="rb")
31  channels = wav_file.getnchannels()
32  num_frames = wav_file.getnframes()
33 
34  if wav_file.getframerate() != sample_rate:
35  raise ValueError(
36  "Audio file should have a sample rate of %d, got %d" % (sample_rate, wav_file.getframerate()))
37 
38  samples = wav_file.readframes(num_frames)
39  wav_file.close()
40 
41  frames = struct.unpack('h' * num_frames * channels, samples)
42 
43  if channels == 2:
44  print("Picovoice processes single-channel audio but stereo file is provided. Processing left channel only.")
45 
46  return frames[::channels]
47 
48  @classmethod
49  def __context_path(cls, context, language):
50  system = platform.system()
51 
52  contexts_root = cls.__append_language('../../resources/contexts', language)
53 
54  if system == 'Darwin':
55  return os.path.join(os.path.dirname(__file__), contexts_root, 'mac', '%s_mac.rhn' % context)
56  elif system == 'Linux':
57  if platform.machine() == 'x86_64':
58  return os.path.join(os.path.dirname(__file__), contexts_root, 'linux', '%s_linux.rhn' % context)
59  else:
60  cpu_info = ''
61  try:
62  cpu_info = subprocess.check_output(['cat', '/proc/cpuinfo']).decode()
63  cpu_part_list = [x for x in cpu_info.split('\n') if 'CPU part' in x]
64  cpu_part = cpu_part_list[0].split(' ')[-1].lower()
65  except Exception as error:
66  raise RuntimeError("Failed to identify the CPU with '%s'\nCPU info: %s" % (error, cpu_info))
67 
68  if '0xb76' == cpu_part or '0xc07' == cpu_part or '0xd03' == cpu_part or '0xd08' == cpu_part:
69  return os.path.join(os.path.dirname(__file__),
70  contexts_root, 'raspberry-pi', '%s_raspberry-pi.rhn' % context)
71  elif '0xd07' == cpu_part:
72  return os.path.join(os.path.dirname(__file__),
73  contexts_root, 'jetson', '%s_jetson.rhn' % context)
74  elif '0xc08' == cpu_part:
75  return os.path.join(os.path.dirname(__file__),
76  contexts_root, 'beaglebone', '%s_beaglebone.rhn' % context)
77  else:
78  raise NotImplementedError("Unsupported CPU: '%s'." % cpu_part)
79  elif system == 'Windows':
80  return os.path.join(os.path.dirname(__file__), contexts_root, 'windows', '%s_windows.rhn' % context)
81  else:
82  raise ValueError("Unsupported system '%s'." % system)
83 
84  @classmethod
85  def __pv_model_path_by_language(cls, relative, language):
86  model_path_subdir = cls.__append_language('lib/common/rhino_params', language)
87  model_path_subdir = '%s.pv' % model_path_subdir
88  return os.path.join(os.path.dirname(__file__), relative, model_path_subdir)
89 
90  rhinos = None
91 
92  @classmethod
93  def setUpClass(cls):
94  _language_to_contexts = {
95  'en': ['coffee_maker'],
96  'es': ['iluminación_inteligente'],
97  'de': ['beleuchtung']
98  }
99 
100  cls.rhinos = dict()
101  for language in _language_to_contexts:
102  cls.rhinos[language] = dict()
103  for context in _language_to_contexts[language]:
104  cls.rhinos[language][context] = Rhino(
105  access_key=sys.argv[1],
106  library_path=pv_library_path('../..'),
107  model_path=cls.__pv_model_path_by_language('../..', language),
108  context_path=cls.__context_path(context, language)
109  )
110 
111  @classmethod
112  def tearDownClass(cls):
113  if cls.rhinos is not None:
114  for language in cls.rhinos:
115  for context in cls.rhinos[language]:
116  cls.rhinos[language][context].delete()
117 
118  def run_rhino(self, language, audio_file_name, context, is_whithin_context, intent=None, slots=None):
119  rhino = self.rhinos[language][context]
120 
121  audio = \
122  self.__read_file(
123  os.path.join(os.path.dirname(__file__), '../../resources/audio_samples/', audio_file_name),
124  rhino.sample_rate)
125 
126  is_finalized = False
127  for i in range(len(audio) // rhino.frame_length):
128  frame = audio[i * rhino.frame_length:(i + 1) * rhino.frame_length]
129  is_finalized = rhino.process(frame)
130  if is_finalized:
131  break
132 
133  self.assertTrue(is_finalized, "Failed to finalize.")
134 
135  inference = rhino.get_inference()
136 
137  if is_whithin_context:
138  self.assertTrue(inference.is_understood, "Couldn't understand.")
139 
140  self.assertEqual(intent, inference.intent, "Incorrect intent.")
141 
142  self.assertEqual(slots, inference.slots, "Incorrect slots.")
143  else:
144  self.assertFalse(inference.is_understood, "Shouldn't be able to understand.")
145 
147  self.run_rhino(
148  language='en',
149  audio_file_name='test_within_context.wav',
150  context='coffee_maker',
151  is_whithin_context=True,
152  intent='orderBeverage',
153  slots=dict(beverage='americano', numberOfShots='double shot', size='medium'))
154 
156  self.run_rhino(
157  language='en',
158  audio_file_name='test_out_of_context.wav',
159  context='coffee_maker',
160  is_whithin_context=False)
161 
163  self.run_rhino(
164  language='es',
165  audio_file_name='test_within_context_es.wav',
166  context='iluminación_inteligente',
167  is_whithin_context=True,
168  intent='changeColor',
169  slots=dict(location='habitación', color='rosado'))
170 
172  self.run_rhino(
173  language='es',
174  audio_file_name='test_out_of_context_es.wav',
175  context='iluminación_inteligente',
176  is_whithin_context=False)
177 
179  self.run_rhino(
180  language='de',
181  audio_file_name='test_within_context_de.wav',
182  context='beleuchtung',
183  is_whithin_context=True,
184  intent='changeState',
185  slots=dict(state='aus'))
186 
188  self.run_rhino(
189  language='de',
190  audio_file_name='test_out_of_context_de.wav',
191  context='beleuchtung',
192  is_whithin_context=False
193  )
194 
195 
196 if __name__ == '__main__':
197  if len(sys.argv) != 2:
198  print("usage: test_rhino.py ${ACCESS_KEY}")
199  exit(1)
200 
201  unittest.main(argv=sys.argv[:1])
python.test_rhino.RhinoTestCase.test_out_of_context_de
def test_out_of_context_de(self)
Definition: test_rhino.py:187
python.test_rhino.RhinoTestCase.run_rhino
def run_rhino(self, language, audio_file_name, context, is_whithin_context, intent=None, slots=None)
Definition: test_rhino.py:118
python.rhino.Rhino
Definition: rhino.py:66
python.util.pv_library_path
def pv_library_path(relative)
Definition: porcupine/binding/python/util.py:80
python.test_rhino.RhinoTestCase.__pv_model_path_by_language
def __pv_model_path_by_language(cls, relative, language)
Definition: test_rhino.py:85
python.test_rhino.RhinoTestCase.test_within_context_de
def test_within_context_de(self)
Definition: test_rhino.py:178
python.test_rhino.RhinoTestCase.test_out_of_context
def test_out_of_context(self)
Definition: test_rhino.py:155
python.test_rhino.RhinoTestCase.rhinos
rhinos
Definition: test_rhino.py:90
python.test_rhino.RhinoTestCase.__context_path
def __context_path(cls, context, language)
Definition: test_rhino.py:49
python.test_rhino.RhinoTestCase.__append_language
def __append_language(s, language)
Definition: test_rhino.py:23
python.test_rhino.RhinoTestCase.test_out_of_context_es
def test_out_of_context_es(self)
Definition: test_rhino.py:171
python.test_rhino.RhinoTestCase.test_within_context
def test_within_context(self)
Definition: test_rhino.py:146
python.test_rhino.RhinoTestCase.tearDownClass
def tearDownClass(cls)
Definition: test_rhino.py:112
python.test_rhino.RhinoTestCase.test_within_context_es
def test_within_context_es(self)
Definition: test_rhino.py:162
python.test_rhino.RhinoTestCase.setUpClass
def setUpClass(cls)
Definition: test_rhino.py:93
python.test_rhino.RhinoTestCase
Definition: test_rhino.py:21
python.test_rhino.RhinoTestCase.__read_file
def __read_file(file_name, sample_rate)
Definition: test_rhino.py:29


picovoice_driver
Author(s):
autogenerated on Fri Apr 1 2022 02:14:55