Implement barge-in for Android TTS

812 Views Asked by At

I am having difficulty figuring out how to resolve this issue, I am not sure if I am not setting up threads correctly or if it is even possible to resolve things properly.

This is an Android app that reads certain strings out as TTS (using the native Android TTS) at certain timings. During this TTS reading, the user should be able to barge-in with instructions such as "Stop" or "Pause." This recognition is done by using the iSpeech API.

Our current solution is to have the TTS running as a Thread that will output the proper strings. Once the user presses a button to begin the voice recognition (using an Intent), the app does voice recognition and handles it perfectly, but then TTS never again outputs anything. Logcat shows the following error:

11-28 02:18:57.072: W/TextToSpeech(16383): speak failed: not bound to TTS engine

I have thought about making the voice recognition a thread of its own that pauses the TTS, but the problem would then be that the timer controlling the TTS would become unsynced with what it should be.

Any advice or help would be appreciated.

Relevant code regarding the thread and the intent are below:

Thread

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Prevent device from sleeping mid build.
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    setContentView(R.layout.activity_build_order);
    mPlayer = MediaPlayer.create(BuildOrderActivity.this, R.raw.bing);
    params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");
    tts = new TextToSpeech(BuildOrderActivity.this, new TextToSpeech.OnInitListener() {
        @SuppressWarnings("deprecation")
        public void onInit(int status) {
            if(status != TextToSpeech.ERROR)
            {
                tts.setLanguage(Locale.US);
                tts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {

                    public void onUtteranceCompleted(String utteranceId) {
                        mPlayer.start();
                    }

                });
            }
        }
    });

    buttonStart = (Button) findViewById(R.id.buttonStartBuild);

    buttonStart.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            startBuild = new StartBuildRunnable();
            Thread t = new Thread(startBuild);
            t.start();
        }
    });

...//code continues oncreate setup for the view}
public class StartBuildRunnable implements Runnable {

    public void run() {
        double delay;
        buildActions = parseBuildXMLAction();
        buildTimes = parseBuildXMLTime();
        say("Build has started");
        delayForNextAction((getSeconds(buildTimes.get(0)) * 1000));
        say(buildActions.get(0));
        for (int i = 1; i < buildActions.size(); i++)
        {
            delay = calcDelayUntilNextAction(buildTimes.get(i - 1), buildTimes.get(i));
            delayForNextAction((long) (delay * 1000));
            say(buildActions.get(i));
            //listViewBuildItems.setSelection(i);
        }
        say("Build has completed");
    }
}

Intent

/**
 * Fire an intent to start the speech recognition activity.
 * @throws InvalidApiKeyException 
 */
private void startRecognition() {
    setupFreeFormDictation();
    try {
        recognizer.startRecord(new SpeechRecognizerEvent() {
            @Override
            public void onRecordingComplete() {
                updateInfoMessage("Recording completed.");
            }

            @Override
            public void onRecognitionComplete(SpeechResult result) {
                Log.v(TAG, "Recognition complete");
                //TODO: Once something is recognized, tie it to an action and continue recognizing.
                //      currently recognizes something in the grammar and then stops listening until
                //      the next button press.
                if (result != null) {
                    Log.d(TAG, "Text Result:" + result.getText());
                    Log.d(TAG, "Text Conf:" + result.getConfidence());

                    updateInfoMessage("Result: " + result.getText() + "\n\nconfidence: " + result.getConfidence());                     
                } else
                    Log.d(TAG, "Result is null...");
            }

            @Override
            public void onRecordingCancelled() {
                updateInfoMessage("Recording cancelled.");
            }

            @Override
            public void onError(Exception exception) {
                updateInfoMessage("ERROR: " + exception.getMessage());
                exception.printStackTrace();
            }
        });
    } catch (BusyException e) {
        e.printStackTrace();
    } catch (NoNetworkException e) {
        e.printStackTrace();
    }
}
0

There are 0 best solutions below