diff --git a/recipes/llm-voice-assistant/android/llm-voice-assistant/build.gradle b/recipes/llm-voice-assistant/android/llm-voice-assistant/build.gradle index f362db9..0fa58c7 100644 --- a/recipes/llm-voice-assistant/android/llm-voice-assistant/build.gradle +++ b/recipes/llm-voice-assistant/android/llm-voice-assistant/build.gradle @@ -65,6 +65,6 @@ dependencies { implementation 'ai.picovoice:android-voice-processor:1.0.2' implementation 'ai.picovoice:porcupine-android:3.0.1' implementation 'ai.picovoice:cheetah-android:2.0.0' - implementation 'ai.picovoice:picollm-android:1.2.0' + implementation 'ai.picovoice:picollm-android:1.2.3' implementation 'ai.picovoice:orca-android:1.0.0' } diff --git a/recipes/llm-voice-assistant/android/llm-voice-assistant/src/main/java/ai/picovoice/llmvoiceassistant/MainActivity.java b/recipes/llm-voice-assistant/android/llm-voice-assistant/src/main/java/ai/picovoice/llmvoiceassistant/MainActivity.java index 5bac9ed..cf6db5f 100644 --- a/recipes/llm-voice-assistant/android/llm-voice-assistant/src/main/java/ai/picovoice/llmvoiceassistant/MainActivity.java +++ b/recipes/llm-voice-assistant/android/llm-voice-assistant/src/main/java/ai/picovoice/llmvoiceassistant/MainActivity.java @@ -15,8 +15,8 @@ import android.Manifest; import android.annotation.SuppressLint; import android.content.pm.PackageManager; +import android.media.AudioAttributes; import android.media.AudioFormat; -import android.media.AudioManager; import android.media.AudioTrack; import android.net.Uri; import android.os.Bundle; @@ -293,6 +293,8 @@ private void runWakeWordSTT(short[] frame) { try { int keywordIndex = porcupine.process(frame); if (keywordIndex == 0) { + interrupt(); + llmPromptText = new StringBuilder(); updateUIState(UIState.STT); } @@ -509,16 +511,26 @@ private void runLLM(String prompt) { ttsPlaybackExecutor.submit(() -> { try { + AudioAttributes audioAttributes = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) + .build(); + + AudioFormat audioFormat = new AudioFormat.Builder() + .setSampleRate(orca.getSampleRate()) + .setEncoding(AudioFormat.ENCODING_PCM_16BIT) + .setChannelMask(AudioFormat.CHANNEL_OUT_MONO) + .build(); + ttsOutput = new AudioTrack( - AudioManager.STREAM_MUSIC, - orca.getSampleRate(), - AudioFormat.CHANNEL_OUT_MONO, - AudioFormat.ENCODING_PCM_16BIT, + audioAttributes, + audioFormat, AudioTrack.getMinBufferSize( orca.getSampleRate(), AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT), - AudioTrack.MODE_STREAM); + AudioTrack.MODE_STREAM, + 0); ttsOutput.play(); } catch (Exception e) { @@ -535,12 +547,15 @@ private void runLLM(String prompt) { while (isQueueingPcm.get() || !pcmQueue.isEmpty()) { short[] pcm = pcmQueue.poll(); - if (pcm != null && pcm.length > 0 && currentState == UIState.LLM_TTS) { + if (pcm != null && pcm.length > 0 && ttsOutput.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { ttsOutput.write(pcm, 0, pcm.length); } } - ttsOutput.stop(); + if (ttsOutput.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { + ttsOutput.flush(); + ttsOutput.stop(); + } ttsOutput.release(); }); } @@ -548,9 +563,8 @@ private void runLLM(String prompt) { private void interrupt() { try { picollm.interrupt(); - if (ttsOutput != null) { + if (ttsOutput != null && ttsOutput.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { ttsOutput.stop(); - ttsOutput.release(); } } catch (PicoLLMException e) { onEngineProcessError(e.getMessage()); @@ -584,7 +598,6 @@ private void onEngineProcessError(String message) { mainHandler.post(() -> chatText.setText(message)); } - private void startWakeWordListening() { if (voiceProcessor.hasRecordAudioPermission(this)) { try { @@ -708,7 +721,7 @@ private void updateUIState(UIState state) { chatText.setText(""); statusProgress.setVisibility(View.VISIBLE); statusText.setVisibility(View.VISIBLE); - statusText.setText("Generating..."); + statusText.setText("Generating...\nSay 'Picovoice' to interrupt"); clearTextButton.setEnabled(false); clearTextButton.setImageDrawable( ResourcesCompat.getDrawable( diff --git a/res/.lint/spell-check/dict.txt b/res/.lint/spell-check/dict.txt index b654661..7dcd90d 100644 --- a/res/.lint/spell-check/dict.txt +++ b/res/.lint/spell-check/dict.txt @@ -23,6 +23,7 @@ pico picollm picovoice pids +playstate pllm psutil pvcheetah