How to make porcupine detect a wake word and then start listening for user input

577 views Asked by At

I have been trying to implement a way that the application detects wake word like "Hey google" or "Jarvis". I did some research and found out porcupine helps towards solving the wake word problem but now the problem is I can't seem to trigger startRecognition() to listen again for the user input and then carry forward with it. I still tried to trigger startRecognition() but then it was asking me to do speechRecognizer.Destroy() which I tried doing with the porcupine onDestroy method but then it just stopped working. Sorry if I confused anyone, I will attach my code I will really appreciate everyone's help as I have been trying to solve this problem for a while now.

Another question is what does the following line of code do?

PendingIntent contentIntent = PendingIntent.getActivity(
                                    this,
                                    0,
                                    new Intent(this, MainActivity.class), // this line ?
                                    0);

The code currently :(

public class PorcupineService extends Service {

    private static final int REQUEST_RECORD_AUDIO_PERMISSION_CODE = 1;
    private SpeechRecognizer speechRecognizer;
    TextToSpeech textToSpeech;
    String userResponse;
    Float speechRate = 2f;

    private static final String CHANNEL_ID = "PorcupineServiceChannel";
    private PorcupineManager porcupineManager;

    private int numUtterances;

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel notificationChannel = new NotificationChannel(
                    CHANNEL_ID,
                    "Porcupine",
                    NotificationManager.IMPORTANCE_HIGH);

            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(notificationChannel);
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        createNotificationChannel();

        PendingIntent pendingIntent = PendingIntent.getActivity(
                this,
                0,
                new Intent(this, MainActivity.class),
                0);

        numUtterances = 0;

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("Wake word")
                .setContentText("Service running")
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setContentIntent(pendingIntent)
                .build();

        startForeground(1234, notification);

        try {
            porcupineManager = new PorcupineManager.Builder()
                    .setKeyword(Porcupine.BuiltInKeyword.JARVIS)
                    .setSensitivity(0.7f).build(
                            getApplicationContext(),
                            (keywordIndex) -> {
                                Log.i("YOU SAID IT!", "yesss");

                                textSpeechInitialize();
                                startRecognition();
                                listening();

                                numUtterances++;

                                PendingIntent contentIntent = PendingIntent.getActivity(
                                        this,
                                        0,
                                        new Intent(this, MainActivity.class),
                                        0);

                                final String contentText = numUtterances == 1 ? " time!" : " times!";
                                Notification n = new NotificationCompat.Builder(this, CHANNEL_ID)
                                        .setContentTitle("Wake word")
                                        .setContentText("Detected " + numUtterances + contentText)
                                        .setSmallIcon(R.drawable.ic_launcher_background)
                                        .setContentIntent(contentIntent)
                                        .build();

                                NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                                assert notificationManager != null;
                                notificationManager.notify(1234, n);
                            });
            porcupineManager.start();
        } catch (PorcupineException e) {
            Log.e("PORCUPINE", e.toString());
        }

        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        try {
            porcupineManager.stop();
            porcupineManager.delete();
            speechRecognizer.destroy();
        } catch (PorcupineException e) {
            Log.e("PORCUPINE", e.toString());
        }

        super.onDestroy();
    }

    public void listening(){
        speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
        speechRecognizer.setRecognitionListener(new RecognitionListener() {

            @Override
            public void onReadyForSpeech(Bundle params) {
            }

            @Override
            public void onBeginningOfSpeech() {}

            @Override
            public void onRmsChanged(float rmsdB) {}

            @Override
            public void onBufferReceived(byte[] buffer) {}

            @Override
            public void onEndOfSpeech() {}

            @Override
            public void onError(int error) {
                String errorMessage = getErrorText(error);
                Log.i(">>> INFO", "Failed " + errorMessage);
            }

            @Override
            public void onResults(Bundle results) {
                ArrayList<String> matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
                userResponse = matches.get(0);
                userResponse = userResponse.toLowerCase();
                toSpeak(userResponse);
            }

            @Override
            public void onPartialResults(Bundle partialResults) {}

            @Override
            public void onEvent(int eventType, Bundle params) {}

        });
    }

    public void textSpeechInitialize(){
        textToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status == TextToSpeech.SUCCESS){
                    textToSpeech.setLanguage(Locale.getDefault());
                    textToSpeech.setSpeechRate(speechRate);
                    String greet = greetings();
                    toSpeak(greet);
                    startRecognition();
                } else {
                    Toast.makeText(getApplicationContext(), "Feature not supported", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    public String getErrorText(int errorCode) {
        String message;
        switch (errorCode) {
            ...
        }
        return message;
    }

    public static String greetings(){
        String s = "";
        Calendar c = Calendar.getInstance();
        int time = c.get(Calendar.HOUR_OF_DAY);

        if (time >= 0 && time < 12){
            s = "Good Morning sir! how can I help you today?";
        } else if (time >= 12 && time < 16){
            s = "Good Afternoon sir";
        } else if (time >= 16 && time < 22){
            s = "Good Evening sir";
        }
        else if (time >= 22 && time < 24){
            s = "Hello sir, you need to take some rest... its getting late!";
        }
        return s;
    }

    private void startRecognition() {
        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getPackageName());
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en");
        speechRecognizer.startListening(intent);
    }

    private void toSpeak(String toSpeak){

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Log.i(">>>Voice Info", String.valueOf(textToSpeech.getVoice()));
        }
        try {
            textToSpeech.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}
0

There are 0 answers