Stuck with Java Speech API?
Tags: 100daysofcode, challenge, java, beginners
Published: 2023-02-23 16:59:24

If you find adding voice inputs to a Java application difficult, you're not alone. JDK's Speech API relies on outdated products and third-party cloud providers. 

But we have a good news, on day 37, we'll add custom voice commands, like `Jarvis, turn off the lights`, with [Picovoice Java SDK](https://picovoice.ai/docs/quick-start/picovoice-java/).

The Picovoice SDK combines [Porcupine Wake Word](https://picovoice.ai/platform/porcupine/) and [Rhino Speech-to-Intent](https://picovoice.ai/platform/rhino/) engines. Wake words like `Jarvis`, powered by Porcupine and follow-up commands like `turn off the lights` powered by Rhino.

Let's get started
1. Get the latest version of the SDK from  Maven Central Repository:
```
ai.picovoice:picovoice-java:${version}
```
2. Design and train models on the Picovoice Platform
While developers can train and adapt custom voice AI models on the Picovoice Console. However, you can use pre-trained ones, too! For this tutorial, we'll use the pre-trained `[Jarvis](https://github.com/Picovoice/porcupine/tree/master/resources/keyword_files)` wake word and the `[Smart Lighting](https://github.com/Picovoice/rhino/tree/master/resources/contexts)` context, which understands commands that change the color/state of lights. 
3. Get an AccessKey Picovoice 
If you still haven't, create an account on the [Picovoice Console](https://console.picovoice.ai/) for free and grab your `AccessKey`.
4. Initialize the Picovoice Platform

```
import ai.picovoice.picovoice.*;

final String accessKey = "..."; // your Picovoice AccessKey
final String keywordPath = "res/path/to/jarvis.ppn";
final String contextPath = "res/path/to/smart_lighting.rhn";

PicovoiceWakeWordCallback wakeWordCallback = () -> { 
  System.out.println("Wake word detected!");
  // let user know wake word was detected
};
PicovoiceInferenceCallback inferenceCallback = inference -> { 
  if (inference.getIsUnderstood()) {
    final String intent = inference.getIntent();
    final Map<String, String> slots = inference.getSlots();
    // use intent and slots to trigger action
  }
}; 

Picovoice picovoice = new Picovoice.Builder()
                    .setAccessKey(accessKey)
                    .setKeywordPath(keywordPath)
                    .setWakeWordCallback(wakeWordCallback)
                    .setContextPath(contextPath)
                    .setInferenceCallback(inferenceCallback)
                    .build();
```
Do not forget to replace `AccessKey`, `KeywordPath`, and `ContextPath` placeholders. Copy your AccessKey from Picovoice Console. The path for the downloaded Porcupine keyword and Rhino Context files, depends on where you save them when you download.

5. Read and Process Microphone Audio
```
import javax.sound.sampled.*;

// get default audio capture device
AudioFormat format = new AudioFormat(16000f, 16, 1, true, false);
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, format);
TargetDataLine micDataLine;
try {
    micDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
    micDataLine.open(format);
} catch (LineUnavailableException e) {
    System.err.println("Failed to get a valid audio capture device.");    
    return;
}

// start audio capture
micDataLine.start();
```
6. Create a loop that reads microphone data and passes it to Picovoice:

```
// buffers for processing audio
short[] picovoiceBuffer = new short[picovoice.getFrameLength()];
ByteBuffer captureBuffer = ByteBuffer.allocate(picovoice.getFrameLength() * 2);
captureBuffer.order(ByteOrder.LITTLE_ENDIAN);

int numBytesRead;
boolean recordingCancelled = false;
while (!recordingCancelled) {

    // read a buffer of audio
    numBytesRead = micDataLine.read(captureBuffer.array(), 0, captureBuffer.capacity());

    // don't pass to Picovoice if we don't have a full buffer
    if (numBytesRead != picovoice.getFrameLength() * 2) {
        continue;
    }

    // copy into 16-bit buffer
    captureBuffer.asShortBuffer().get(picovoiceBuffer);

    // process with picovoice
    picovoice.process(picovoiceBuffer);
}
```
This tutorial was originally published on [Medium](https://medium.com/picovoice/prioritizing-privacy-add-offline-speech-recognition-to-a-java-application-1c864574fb7e)

Resources:
[Source Code](https://github.com/Picovoice/picovoice/tree/master/demo/java-swing)
[Picovoice](https://picovoice.ai/)
Picovoice Java SDK (https://picovoice.ai/docs/quick-start/picovoice-java/)