package github.nisrulz.example.usingpocketsphinxforvoicerecognition;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import edu.cmu.pocketsphinx.Assets;
import edu.cmu.pocketsphinx.Hypothesis;
import edu.cmu.pocketsphinx.SpeechRecognizer;
import edu.cmu.pocketsphinx.SpeechRecognizerSetup;
import static edu.cmu.pocketsphinx.SpeechRecognizerSetup.defaultSetup;
public class SpeechRecognizerManager {
/* Named searches allow to quickly reconfigure the decoder */
private static final String KWS_SEARCH = "wakeup";
/* Keyword we are looking for to activate menu */
private static String HOTWORD;
private SpeechRecognizer mPocketSphinxRecognizer;
private static final String TAG = SpeechRecognizerManager.class.getSimpleName();
protected Intent mSpeechRecognizerIntent;
protected android.speech.SpeechRecognizer mGoogleSpeechRecognizer;
private Context mContext;
OnResultListener onResultListener;
public SpeechRecognizerManager(Context context) {
this.mContext = context;
HOTWORD = context.getResources().getString(R.string.hotword);
initPockerSphinx();
initGoogleSpeechRecognizer();
}
public void setOnResultListener(OnResultListener onResultListener) {
this.onResultListener = onResultListener;
}
private void initPockerSphinx() {
new AsyncTask<Void, Void, Exception>() {
@Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(mContext);
//Performs the synchronization of assets in the application and external storage
File assetDir = assets.syncAssets();
//Creates a new SpeechRecognizer builder with a default configuration
SpeechRecognizerSetup speechRecognizerSetup = defaultSetup();
//Set Dictionary and Acoustic Model files
speechRecognizerSetup.setAcousticModel(new File(assetDir, "en-us-ptm"));
speechRecognizerSetup.setDictionary(new File(assetDir, "cmudict-en-us.dict"));
// Threshold to tune for keyphrase to balance between false positives and false negatives
speechRecognizerSetup.setKeywordThreshold(1e-45f);
//Creates a new SpeechRecognizer object based on previous set up.
mPocketSphinxRecognizer = speechRecognizerSetup.getRecognizer();
mPocketSphinxRecognizer.addListener(new PocketSphinxRecognitionListener());
// Create keyword-activation search.
mPocketSphinxRecognizer.addKeyphraseSearch(KWS_SEARCH, HOTWORD);
} catch (IOException e) {
return e;
}
return null;
}
@Override
protected void onPostExecute(Exception result) {
if (result != null) {
Toast.makeText(mContext, "Failed to init mPocketSphinxRecognizer ", Toast.LENGTH_SHORT).show();
} else {
restartSearch(KWS_SEARCH);
}
}
}.execute();
}
private void initGoogleSpeechRecognizer() {
mGoogleSpeechRecognizer = android.speech.SpeechRecognizer
.createSpeechRecognizer(mContext);
mGoogleSpeechRecognizer.setRecognitionListener(new GoogleRecognitionListener());
mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CONFIDENCE_SCORES, true);
}
public void destroy() {
if (mPocketSphinxRecognizer != null) {
mPocketSphinxRecognizer.cancel();
mPocketSphinxRecognizer.shutdown();
mPocketSphinxRecognizer = null;
}
if (mGoogleSpeechRecognizer != null) {
mGoogleSpeechRecognizer.cancel();
;
mGoogleSpeechRecognizer.destroy();
mPocketSphinxRecognizer = null;
}
}
private void restartSearch(String searchName) {
mPocketSphinxRecognizer.stop();
mPocketSphinxRecognizer.startListening(searchName);
}
protected class PocketSphinxRecognitionListener implements edu.cmu.pocketsphinx.RecognitionListener {
@Override
public void onBeginningOfSpeech() {
}
/**
* In partial result we get quick updates about current hypothesis. In
* keyword spotting mode we can react here, in other modes we need to wait
* for final result in onResult.
*/
@Override
public void onPartialResult(Hypothesis hypothesis) {
if (hypothesis == null) {
return;
}
String text = hypothesis.getHypstr();
Log.d(TAG, text);
if (text.contains(HOTWORD)) {
mPocketSphinxRecognizer.cancel();
mGoogleSpeechRecognizer.startListening(mSpeechRecognizerIntent);
Toast.makeText(mContext, "You said: " + text, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onResult(Hypothesis hypothesis) {
}
/**
* We stop mPocketSphinxRecognizer here to get a final result
*/
@Override
public void onEndOfSpeech() {
}
public void onError(Exception error) {
}
@Override
public void onTimeout() {
}
}
protected class GoogleRecognitionListener implements
android.speech.RecognitionListener {
private final String TAG = GoogleRecognitionListener.class
.getSimpleName();
@Override
public void onBeginningOfSpeech() {
}
@Override
public void onEndOfSpeech() {
}
@Override
public void onReadyForSpeech(Bundle params) {
}
@Override
public void onRmsChanged(float rmsdB) {
}
@Override
public void onBufferReceived(byte[] buffer) {
}
@Override
public void onError(int error) {
Log.e(TAG, "onError:" + error);
mPocketSphinxRecognizer.startListening(KWS_SEARCH);
}
@Override
public void onPartialResults(Bundle partialResults) {
}
@Override
public void onResults(Bundle results) {
if ((results != null)
&& results.containsKey(android.speech.SpeechRecognizer.RESULTS_RECOGNITION)) {
ArrayList<String> heard = results
.getStringArrayList(android.speech.SpeechRecognizer.RESULTS_RECOGNITION);
float[] scores = results
.getFloatArray(android.speech.SpeechRecognizer.CONFIDENCE_SCORES);
for (int i = 0; i < heard.size(); i++) {
Log.d(TAG, "onResultsheard:" + heard.get(i)
+ " confidence:" + scores[i]);
}
//send list of words to activity
onResultListener.OnResult(heard);
}
mPocketSphinxRecognizer.startListening(KWS_SEARCH);
}
@Override
public void onEvent(int eventType, Bundle params) {
}
}
public interface OnResultListener {
void OnResult(ArrayList<String> commands);
}
}