rhino/demo/java/src/ai/picovoice/rhinodemo/MicDemo.java
Go to the documentation of this file.
1 /*
2  Copyright 2018-2021 Picovoice Inc.
3 
4  You may not use this file except in compliance with the license. A copy of the license is
5  located in the "LICENSE" file accompanying this source.
6 
7  Unless required by applicable law or agreed to in writing, software distributed under the
8  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
9  express or implied. See the License for the specific language governing permissions and
10  limitations under the License.
11 */
12 
13 package ai.picovoice.rhinodemo;
14 
15 import ai.picovoice.rhino.*;
16 import org.apache.commons.cli.*;
17 
18 import java.io.File;
19 import java.io.IOException;
20 import java.io.ByteArrayInputStream;
21 import java.io.ByteArrayOutputStream;
22 import java.nio.ByteBuffer;
23 import java.nio.ByteOrder;
24 import java.util.Map;
25 import javax.sound.sampled.*;
26 
27 public class MicDemo {
28  public static void runDemo(String accessKey, String contextPath, String libraryPath, String modelPath,
29  float sensitivity, int audioDeviceIndex, String outputPath, boolean requireEndpoint) {
30 
31  // for file output
32  File outputFile = null;
33  ByteArrayOutputStream outputStream = null;
34  long totalBytesCaptured = 0;
35  AudioFormat format = new AudioFormat(16000f, 16, 1, true, false);
36 
37  // get audio capture device
38  DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, format);
39  TargetDataLine micDataLine;
40  try {
41  micDataLine = getAudioDevice(audioDeviceIndex, dataLineInfo);
42  micDataLine.open(format);
43  } catch (LineUnavailableException e) {
44  System.err.println("Failed to get a valid capture device. Use --show_audio_devices to " +
45  "show available capture devices and their indices");
46  System.exit(1);
47  return;
48  }
49 
50  Rhino rhino = null;
51  try {
52 
53  rhino = new Rhino.Builder()
54  .setAccessKey(accessKey)
55  .setContextPath(contextPath)
56  .setLibraryPath(libraryPath)
57  .setModelPath(modelPath)
58  .setSensitivity(sensitivity)
59  .setRequireEndpoint(requireEndpoint)
60  .build();
61 
62  if (outputPath != null) {
63  outputFile = new File(outputPath);
64  outputStream = new ByteArrayOutputStream();
65  }
66 
67  micDataLine.start();
68 
69  System.out.println(rhino.getContextInformation());
70  System.out.println("Press enter to stop recording.");
71  System.out.println("Listening...");
72 
73  // buffers for processing audio
74  int frameLength = rhino.getFrameLength();
75  ByteBuffer captureBuffer = ByteBuffer.allocate(frameLength * 2);
76  captureBuffer.order(ByteOrder.LITTLE_ENDIAN);
77  short[] rhinoBuffer = new short[frameLength];
78 
79  int numBytesRead;
80  while (System.in.available() == 0) {
81 
82  // read a buffer of audio
83  numBytesRead = micDataLine.read(captureBuffer.array(), 0, captureBuffer.capacity());
84  totalBytesCaptured += numBytesRead;
85 
86  // write to output if we're recording
87  if (outputStream != null) {
88  outputStream.write(captureBuffer.array(), 0, numBytesRead);
89  }
90 
91  // don't pass to rhino if we don't have a full buffer
92  if (numBytesRead != frameLength * 2) {
93  continue;
94  }
95 
96  // copy into 16-bit buffer
97  captureBuffer.asShortBuffer().get(rhinoBuffer);
98 
99  // process with rhino
100  boolean isFinalized = rhino.process(rhinoBuffer);
101  if (isFinalized) {
102 
103  RhinoInference inference = rhino.getInference();
104  if (inference.getIsUnderstood()) {
105 
106  System.out.println("{");
107  System.out.println(String.format(" intent : '%s'", inference.getIntent()));
108  System.out.println(" slots : {");
109  for (Map.Entry<String, String> slot : inference.getSlots().entrySet()) {
110  System.out.println(String.format(" %s : '%s'", slot.getKey(), slot.getValue()));
111  }
112  System.out.println(" }");
113  System.out.println("}");
114  } else {
115  System.out.println("Didn't understand the command.");
116  }
117  }
118  }
119  System.out.println("Stopping...");
120  } catch (Exception e) {
121  System.err.println(e.toString());
122  } finally {
123  if (outputStream != null && outputFile != null) {
124 
125  // need to transfer to input stream to write
126  ByteArrayInputStream writeArray = new ByteArrayInputStream(outputStream.toByteArray());
127  AudioInputStream writeStream = new AudioInputStream(writeArray, format, totalBytesCaptured / format.getFrameSize());
128 
129  try {
130  AudioSystem.write(writeStream, AudioFileFormat.Type.WAVE, outputFile);
131  } catch (IOException e) {
132  System.err.printf("Failed to write audio to '%s'.\n", outputFile.getPath());
133  e.printStackTrace();
134  }
135  }
136 
137  if (rhino != null) {
138  rhino.delete();
139  }
140  }
141  }
142 
143  private static void showAudioDevices() {
144 
145  // get available audio devices
146  Mixer.Info[] allMixerInfo = AudioSystem.getMixerInfo();
147  Line.Info captureLine = new Line.Info(TargetDataLine.class);
148 
149  for (int i = 0; i < allMixerInfo.length; i++) {
150 
151  // check if supports capture in the format we need
152  Mixer mixer = AudioSystem.getMixer(allMixerInfo[i]);
153  if (mixer.isLineSupported(captureLine)) {
154  System.out.printf("Device %d: %s\n", i, allMixerInfo[i].getName());
155  }
156  }
157  }
158 
159  private static TargetDataLine getDefaultCaptureDevice(DataLine.Info dataLineInfo) throws LineUnavailableException {
160 
161  if (!AudioSystem.isLineSupported(dataLineInfo)) {
162  throw new LineUnavailableException("Default capture device does not support the audio " +
163  "format required by Picovoice (16kHz, 16-bit, linearly-encoded, single-channel PCM).");
164  }
165 
166  return (TargetDataLine) AudioSystem.getLine(dataLineInfo);
167  }
168 
169  private static TargetDataLine getAudioDevice(int deviceIndex, DataLine.Info dataLineInfo) throws LineUnavailableException {
170 
171  if (deviceIndex >= 0) {
172  try {
173  Mixer.Info mixerInfo = AudioSystem.getMixerInfo()[deviceIndex];
174  Mixer mixer = AudioSystem.getMixer(mixerInfo);
175 
176  if (mixer.isLineSupported(dataLineInfo)) {
177  return (TargetDataLine) mixer.getLine(dataLineInfo);
178  } else {
179  System.err.printf("Audio capture device at index %s does not support the audio format required by " +
180  "Picovoice. Using default capture device.", deviceIndex);
181  }
182  } catch (Exception e) {
183  System.err.printf("No capture device found at index %s. Using default capture device.", deviceIndex);
184  }
185  }
186 
187  // use default capture device if we couldn't get the one requested
188  return getDefaultCaptureDevice(dataLineInfo);
189  }
190 
191  public static void main(String[] args) {
192 
193  Options options = BuildCommandLineOptions();
194  CommandLineParser parser = new DefaultParser();
195  HelpFormatter formatter = new HelpFormatter();
196 
197  CommandLine cmd;
198  try {
199  cmd = parser.parse(options, args);
200  } catch (ParseException e) {
201  System.out.println(e.getMessage());
202  formatter.printHelp("rhinomicdemo", options);
203  System.exit(1);
204  return;
205  }
206 
207  if (cmd.hasOption("help")) {
208  formatter.printHelp("rhinomicdemo", options);
209  return;
210  }
211 
212  if (cmd.hasOption("show_audio_devices")) {
214  return;
215  }
216 
217  String accessKey = cmd.getOptionValue("access_key");
218  String libraryPath = cmd.getOptionValue("library_path");
219  String modelPath = cmd.getOptionValue("model_path");
220  String contextPath = cmd.getOptionValue("context_path");
221  String sensitivityStr = cmd.getOptionValue("sensitivity");
222  String audioDeviceIndexStr = cmd.getOptionValue("audio_device_index");
223  String outputPath = cmd.getOptionValue("output_path");
224  String requireEndpointValue = cmd.getOptionValue("require_endpoint");
225 
226  if (accessKey == null || accessKey.length() == 0) {
227  throw new IllegalArgumentException("AccessKey is required for Rhino.");
228  }
229 
230  // parse sensitivity
231  float sensitivity = 0.5f;
232  if (sensitivityStr != null) {
233  try {
234  sensitivity = Float.parseFloat(sensitivityStr);
235  } catch (Exception e) {
236  throw new IllegalArgumentException("Failed to parse sensitivity value. " +
237  "Must be a floating-point number between [0,1].");
238  }
239 
240  if (sensitivity < 0 || sensitivity > 1) {
241  throw new IllegalArgumentException(String.format("Failed to parse sensitivity value (%s). " +
242  "Must be a floating-point number between [0,1].", sensitivity));
243  }
244  }
245 
246  if(contextPath == null){
247  throw new IllegalArgumentException("No context file provided. This is a required argument.");
248  }
249  File contextFile = new File(contextPath);
250  if (!contextFile.exists()) {
251  throw new IllegalArgumentException(String.format("Context file at path '%s' does not exist", contextPath));
252  }
253 
254  if (libraryPath == null) {
255  libraryPath = Rhino.LIBRARY_PATH;
256  }
257 
258  if (modelPath == null) {
259  modelPath = Rhino.MODEL_PATH;
260  }
261 
262  int audioDeviceIndex = -1;
263  if (audioDeviceIndexStr != null) {
264  try {
265  audioDeviceIndex = Integer.parseInt(audioDeviceIndexStr);
266  if (audioDeviceIndex < 0) {
267  throw new IllegalArgumentException(String.format("Audio device index %s is not a " +
268  "valid positive integer.", audioDeviceIndexStr));
269  }
270  } catch (Exception e) {
271  throw new IllegalArgumentException(String.format("Audio device index '%s' is not a " +
272  "valid positive integer.", audioDeviceIndexStr));
273  }
274  }
275 
276  boolean requireEndpoint = true;
277  if (requireEndpointValue != null && requireEndpointValue.toLowerCase().equals("false")) {
278  requireEndpoint = false;
279  }
280 
281  runDemo(accessKey, contextPath, libraryPath, modelPath, sensitivity, audioDeviceIndex, outputPath, requireEndpoint);
282  }
283 
284  private static Options BuildCommandLineOptions() {
285  Options options = new Options();
286 
287  options.addOption(Option.builder("a")
288  .longOpt("access_key")
289  .hasArg(true)
290  .desc("AccessKey obtained from Picovoice Console (https://picovoice.ai/console/).")
291  .build());
292 
293  options.addOption(Option.builder("c")
294  .longOpt("context_path")
295  .hasArg(true)
296  .desc("Absolute path to context file.")
297  .build());
298 
299  options.addOption(Option.builder("l")
300  .longOpt("library_path")
301  .hasArg(true)
302  .desc("Absolute path to the Rhino native runtime library.")
303  .build());
304 
305  options.addOption(Option.builder("m")
306  .longOpt("model_path")
307  .hasArg(true)
308  .desc("Absolute path to the file containing model parameters.")
309  .build());
310 
311  options.addOption(Option.builder("s")
312  .longOpt("sensitivity")
313  .hasArgs()
314  .desc("Inference sensitivity. It should be a number within [0, 1]. A higher sensitivity value results in " +
315  "fewer misses at the cost of (potentially) increasing the erroneous inference rate. " +
316  "If not set 0.5 will be used.")
317  .build());
318 
319  options.addOption(Option.builder("e")
320  .longOpt("require_endpoint")
321  .hasArg(true)
322  .desc("If set to `false`, Rhino does not require an endpoint (chunk of silence) before " +
323  "finishing inference.")
324  .build());
325 
326  options.addOption(Option.builder("o")
327  .longOpt("output_path")
328  .hasArg(true)
329  .desc("Absolute path to recorded audio for debugging.")
330  .build());
331 
332  options.addOption(Option.builder("di")
333  .longOpt("audio_device_index")
334  .hasArg(true)
335  .desc("Index of input audio device.")
336  .build());
337 
338  options.addOption(new Option("sd", "show_audio_devices", false, "Print available recording devices."));
339  options.addOption(new Option("h", "help", false, ""));
340 
341  return options;
342  }
343 }
ai.picovoice.rhino.Rhino.process
boolean process(short[] pcm)
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:90
ai.picovoice.rhinodemo.MicDemo.showAudioDevices
static void showAudioDevices()
Definition: rhino/demo/java/src/ai/picovoice/rhinodemo/MicDemo.java:143
ai.picovoice.rhino.Rhino.Builder.setSensitivity
Builder setSensitivity(float sensitivity)
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:221
ai.picovoice.rhino.Rhino.MODEL_PATH
static final String MODEL_PATH
Definition: java/src/ai/picovoice/rhino/Rhino.java:36
ai.picovoice.rhino.RhinoInference.getIntent
String getIntent()
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/RhinoInference.java:30
ai.picovoice.rhino.Rhino.Builder.setContextPath
Builder setContextPath(String contextPath)
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:216
ai.picovoice.rhino.Rhino.Builder.setAccessKey
Builder setAccessKey(String accessKey)
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:206
getName
ROSCONSOLE_CONSOLE_IMPL_DECL std::string getName(void *handle)
ai.picovoice.rhino.Rhino.LIBRARY_PATH
static final String LIBRARY_PATH
Definition: java/src/ai/picovoice/rhino/Rhino.java:35
f
f
ai.picovoice.rhinodemo.MicDemo.getDefaultCaptureDevice
static TargetDataLine getDefaultCaptureDevice(DataLine.Info dataLineInfo)
Definition: rhino/demo/java/src/ai/picovoice/rhinodemo/MicDemo.java:159
File
ai.picovoice.rhino.Rhino.Builder.setLibraryPath
Builder setLibraryPath(String libraryPath)
Definition: java/src/ai/picovoice/rhino/Rhino.java:192
ai.picovoice.rhinodemo.MicDemo
Definition: rhino/demo/java/src/ai/picovoice/rhinodemo/MicDemo.java:27
ai.picovoice.rhinodemo.MicDemo.getAudioDevice
static TargetDataLine getAudioDevice(int deviceIndex, DataLine.Info dataLineInfo)
Definition: rhino/demo/java/src/ai/picovoice/rhinodemo/MicDemo.java:169
ai.picovoice.rhinodemo.MicDemo.runDemo
static void runDemo(String accessKey, String contextPath, String libraryPath, String modelPath, float sensitivity, int audioDeviceIndex, String outputPath, boolean requireEndpoint)
Definition: rhino/demo/java/src/ai/picovoice/rhinodemo/MicDemo.java:28
ai.picovoice.rhino.RhinoInference
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/RhinoInference.java:15
ai
ai.picovoice.rhino
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/exception/RhinoActivationException.java:11
ai.picovoice
ai.picovoice.rhino.Rhino
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:35
ai.picovoice.rhino.Rhino.Builder.setRequireEndpoint
Builder setRequireEndpoint(boolean requireEndpoint)
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:226
ai.picovoice.rhino.Rhino.Builder.setModelPath
Builder setModelPath(String modelPath)
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:211
ai.picovoice.rhino.Rhino.Builder
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:199
ai.picovoice.rhinodemo.MicDemo.BuildCommandLineOptions
static Options BuildCommandLineOptions()
Definition: rhino/demo/java/src/ai/picovoice/rhinodemo/MicDemo.java:284
ai.picovoice.rhino.Rhino.getInference
RhinoInference getInference()
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:120
ai.picovoice.rhino.RhinoInference.getIsUnderstood
boolean getIsUnderstood()
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/RhinoInference.java:26
args
cmd
string cmd
ai.picovoice.rhino.Rhino.Builder.build
Rhino build(Context context)
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:266
ai.picovoice.rhino.Rhino.getFrameLength
native int getFrameLength()
ai.picovoice.rhino.Rhino.delete
void delete()
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:71
ai.picovoice.rhino.RhinoInference.getSlots
Map< String, String > getSlots()
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/RhinoInference.java:34
ai.picovoice.rhino.Rhino.getContextInformation
String getContextInformation()
Definition: android/Rhino/rhino/src/main/java/ai/picovoice/rhino/Rhino.java:157
ai.picovoice.rhinodemo.MicDemo.main
static void main(String[] args)
Definition: rhino/demo/java/src/ai/picovoice/rhinodemo/MicDemo.java:191


picovoice_driver
Author(s):
autogenerated on Fri Apr 1 2022 02:13:56