I am currently developing a word translator with speech-to-text function. I studied pocketsphinx but I can only let it search the dictionary by declaring a default keyword. Is there a way that you will speak first before it will search the dictionary? I am stucked here. Any help will be appreciated. Thankyou! Here's the code:
/* Named searches allow to quickly reconfigure the decoder */
private static final String KWS_SEARCH = "wakeup";
private static final String FORECAST_SEARCH = "forecast";
private static final String DIGITS_SEARCH = "digits";
private static final String PHONE_SEARCH = "phones";
private static final String MENU_SEARCH = "menu";
/* Keyword we are looking for to activate menu */
private static final String KEYPHRASE = "";
/* Used to handle permission request */
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;
private SpeechRecognizer recognizer;
private HashMap<String, Integer> captions;
private void runRecognizerSetup() {
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(TranslateActivity.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
Toast.makeText(TranslateActivity.this,"Failed to initialize recognizer " + result, Toast.LENGTH_SHORT).show();
popupWindow.dismiss();
} else {
lblPrepare.setText("VOICE RECOGNITION READY");
lblSpeak.setVisibility(View.VISIBLE);
recognizer.startListening(KWS_SEARCH);
}
}
}.execute();
}
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
runRecognizerSetup();
} else {
finish();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (recognizer != null) {
recognizer.cancel();
recognizer.shutdown();
}
}
/**
* 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();
if(text.equals(""))
{
}else
{
Toast.makeText(TranslateActivity.this, text, Toast.LENGTH_SHORT).show();
}
/*if (text.equals(KEYPHRASE)){
recognizer.cancel();
// <- You have to implement this
recognizer.startListening(KWS_SEARCH);
}/*
switchSearch(MENU_SEARCH);
else if (text.equals(DIGITS_SEARCH))
switchSearch(DIGITS_SEARCH);
else if (text.equals(PHONE_SEARCH))
switchSearch(PHONE_SEARCH);
else if (text.equals(FORECAST_SEARCH))
switchSearch(FORECAST_SEARCH);
else
Toast.makeText(TranslateActivity.this,text, Toast.LENGTH_SHORT).show();*/
}
/**
* This callback is called when we stop the recognizer.
*/
#Override
public void onResult(Hypothesis hypothesis) {
/*
if (hypothesis != null) {
String text = hypothesis.getHypstr();
makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}*/
if (hypothesis!=null)
{
popupWindow.dismiss();
performAction(hypothesis);
}
}
#Override
public void onBeginningOfSpeech() {
}
/**
* We stop recognizer here to get a final result
*/
#Override
public void onEndOfSpeech() {
/*if (!recognizer.getSearchName().equals(KWS_SEARCH))
switchSearch(KWS_SEARCH);*/
recognizer.stop();
popupWindow.dismiss();
}
/*private void switchSearch(String searchName) {
recognizer.stop();
// If we are not spotting, start listening with timeout (10000 ms or 10 seconds).
if (searchName.equals(KWS_SEARCH))
recognizer.startListening(searchName);
else
recognizer.startListening(searchName);
Toast.makeText(TranslateActivity.this,searchName, Toast.LENGTH_SHORT).show();
}*/
private void setupRecognizer(File assetsDir) throws IOException {
// The recognizer can be configured to perform multiple searches
// of different kind and switch between them
recognizer = SpeechRecognizerSetup.defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
.setRawLogDir(assetsDir) // To disable logging of raw audio comment out this call (takes a lot of space on the device)
.setKeywordThreshold(1e-45f) // Threshold to tune for keyphrase to balance between false alarms and misses
.setBoolean("-allphone_ci", true) // Use context-independent phonetic search, context-dependent is too slow for mobile
.getRecognizer();
recognizer.addListener(this);
/** In your application you might not need to add all those searches.
* They are added here for demonstration. You can leave just one.
*/
// Create keyword-activation search.
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
// Create grammar-based search for selection between demos
/* File menuGrammar = new File(assetsDir, "menu.gram");
recognizer.addGrammarSearch(MENU_SEARCH, menuGrammar);
// Create grammar-based search for digit recognition
File digitsGrammar = new File(assetsDir, "digits.gram");
recognizer.addGrammarSearch(DIGITS_SEARCH, digitsGrammar);
// Create language model search
File languageModel = new File(assetsDir, "weather.dmp");
recognizer.addNgramSearch(FORECAST_SEARCH, languageModel);
// Phonetic search
File phoneticModel = new File(assetsDir, "en-phone.dmp");
recognizer.addAllphoneSearch(PHONE_SEARCH, phoneticModel);*/
}
#Override
public void onError(Exception error) {
Toast.makeText(TranslateActivity.this,"Failed: "+error.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onTimeout() {
/* switchSearch(KWS_SEARCH);*/
}
public void performAction(Hypothesis hypothesis) {
String strWord = hypothesis.getHypstr();
txtOriginal.setText(strWord);
if(recognizer.getDecoder().lookupWord("abc") == null) {
// do something
}
Toast.makeText(TranslateActivity.this, strWord, Toast.LENGTH_SHORT).show();
}
Related
I want to create a voice recognition app in android and run it in service so i can use it even without in the app. So i looked for reference and i found in GitHub a demo app.
This is the site https://github.com/ihrupin/SpeechRecognitionService
I download the app and also i read the documentation, Yes it running well to me it also running in service, but i really want is for example if i said (open Facebook) it will open the installed Facebook app.
I'm newbie in using the PocketSphinx.
This is the MainActivity
public class MainActivity extends AppCompatActivity {
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;
private static final String LOG_TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((Button)findViewById(R.id.btn)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(LOG_TAG, "onClick");
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
return;
}
startService(new Intent(MainActivity.this, VoiceService.class));
}
});
}
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startService(new Intent(MainActivity.this, VoiceService.class));
} else {
finish();
}
}
}
}
This is my Service
public class VoiceService extends Service implements
RecognitionListener {
private static final String LOG_TAG = VoiceService.class.getSimpleName();
private static final String KWS_SEARCH = "wakeup";
private static final String KEYPHRASE = "lisa";
private SpeechRecognizer recognizer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
runRecognizerSetup();
}
return super.onStartCommand(intent, flags, startId);
}
private void runRecognizerSetup() {
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(VoiceService.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
Log.i(LOG_TAG, "Failed to init recognizer ");
} else {
switchSearch(KWS_SEARCH);
}
}
}.execute();
}
#Override
public void onDestroy() {
super.onDestroy();
if (recognizer != null) {
recognizer.cancel();
recognizer.shutdown();
}
}
#Override
public void onPartialResult(Hypothesis hypothesis) {
if (hypothesis == null)
return;
String text = hypothesis.getHypstr();
if (text.contains(KEYPHRASE)) {
Toast.makeText(this, "onPartialResult text=" + text, Toast.LENGTH_SHORT).show();
switchSearch(KWS_SEARCH);
}
Log.i(LOG_TAG, "onPartialResult text=" +text);
}
#Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
Log.i(LOG_TAG, "onResult text=" +text);
}
}
#Override
public void onBeginningOfSpeech() {
Log.i(LOG_TAG, "onBeginningOfSpeech");
}
#Override
public void onEndOfSpeech() {
if (!recognizer.getSearchName().contains(KWS_SEARCH))
switchSearch(KWS_SEARCH);
Log.i(LOG_TAG, "onEndOfSpeech");
}
private void switchSearch(String searchName) {
Log.i(LOG_TAG, "switchSearch searchName = " + searchName);
recognizer.stop();
recognizer.startListening(searchName, 10000);
}
private void setupRecognizer(File assetsDir) throws IOException {
recognizer = SpeechRecognizerSetup.defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
.setRawLogDir(assetsDir)
.setKeywordThreshold(1e-45f)
.setBoolean("-allphone_ci", true)
.getRecognizer();
recognizer.addListener(this);
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
}
#Override
public void onError(Exception error) {
Log.i(LOG_TAG, "onError " + error.getMessage());
}
#Override
public void onTimeout() {
switchSearch(KWS_SEARCH);
Log.i(LOG_TAG, "onTimeout");
}
}
This is BootReceiver
public class BootReceiver extends BroadcastReceiver {
private static final String LOG_TAG = BootReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
Log.i(LOG_TAG, "onReceive");
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Log.i(LOG_TAG, "onReceive onBoot");
context.startService(new Intent(context, VoiceService.class));
}
}
}
I've researched about this topic and i found out that i must modify the grammar and the dictionary but i don't know how to do that. Any ideas?
If you want to modify the existing grammer and want to add your own words you have to modify it a little bit.
write this line in your recognizer setup method.
recognizer.addKeyphraseSearch("facebookPhrase", "Open Facebook");
To edit this example you can read about on official website here
https://cmusphinx.github.io/wiki/tutoriallm/
I am using PocketSphinx for android-23.
I want to code an offline assistant for one of my apps.
I have successfully used recognizer.addKeyphraseSearch to initialize the assistant. For eg. In this case I say "Hello" to initialize it.
this is my entire code
public class Farmax_2 extends Activity implements
RecognitionListener {
/* Named searches allow to quickly reconfigure the decoder */
private static final String KWS_SEARCH = "wakeup";
private static final String ahead = "about";
private static final String PHONE_SEARCH = "ahead";
private static final String MENU_SEARCH = "menu";
TextToSpeech t1;
Button btn;
/* Keyword we are looking for to activate menu */
private static final String KEYPHRASE = "hello";
/* Used to handle permission request */
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;
private SpeechRecognizer recognizer;
private HashMap<String, Integer> captions;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_farmax_2);
// Check if user has given permission to record audio
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
return;
}
btn=(Button)findViewById(R.id.buttonme);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent inte = new Intent(Farmax_2.this, MainMenu.class);
startActivity(inte);
}
});
t1 = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
t1.setLanguage(Locale.UK);
}
}
});
runRecognizerSetup();
}
public void omku(View view) { Intent in=new Intent(this,abtus.class);
startActivity(in);}
private void runRecognizerSetup() {
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(Farmax_2.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
} else {
switchSearch(KWS_SEARCH);
}
}
}.execute();
}
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
runRecognizerSetup();
} else {
finish();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (recognizer != null) {
recognizer.cancel();
recognizer.shutdown();
}
}
/**
* 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();
switch (text) {
case KEYPHRASE: {
omkar();
break;
}
case ahead: {
Intent in = new Intent(this, abtus.class);
startActivity(in);
break;
// t1.speak("taking you to privacy policy of farmax.", TextToSpeech.QUEUE_FLUSH, null);
}
case PHONE_SEARCH: {
Intent in = new Intent(this, MainMenu.class);
startActivity(in);
// t1.speak("Main Menu.", TextToSpeech.QUEUE_FLUSH, null);
break;
}
}
}
private void omkar() {
t1.speak("Yes sir.", TextToSpeech.QUEUE_FLUSH, null);
switchSearch(MENU_SEARCH);
}
/**
* This callback is called when we stop the recognizer.
*/
#Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBeginningOfSpeech() {
}
/**
* We stop recognizer here to get a final result
*/
#Override
public void onEndOfSpeech() {
}
private void switchSearch(String searchName) {
recognizer.stop();
// If we are not spotting, start listening with timeout (10000 ms or 10 seconds).
if (searchName.equals(KWS_SEARCH))
recognizer.startListening(searchName);
else
recognizer.startListening(searchName, 10000);
}
private void setupRecognizer(File assetsDir) throws IOException {
// The recognizer can be configured to perform multiple searches
// of different kind and switch between them
recognizer = SpeechRecognizerSetup.defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
.setRawLogDir(assetsDir) // To disable logging of raw audio comment out this call (takes a lot of space on the device)
.getRecognizer();
recognizer.addListener(this);
/** In your application you might not need to add all those searches.
* They are added here for demonstration. You can leave just one.
*/
// Create keyword-activation search.
recognizer.addKeyphraseSearch(KWS_SEARCH, "hello");
// Create grammar-based search for selection between demos
File menuGrammar = new File(assetsDir, "firstscn.gram");
recognizer.addGrammarSearch(MENU_SEARCH, menuGrammar);
// Create grammar-based search for digit recognition
}
#Override
public void onError(Exception error) {
}
#Override
public void onTimeout() {
switchSearch(KWS_SEARCH);
}
}
when I say hello, it responds correctly by replying "Yes sir" via tts. But after that it is supposed to switch menu and wait for the further commands. In this case there are two.
#Override
public void onPartialResult(Hypothesis hypothesis) {
if (hypothesis == null)
return;
String text = hypothesis.getHypstr();
switch (text) {
case KEYPHRASE: {
omkar();
break;
}
case ahead: {
Intent in = new Intent(this, abtus.class);
startActivity(in);
break;
// t1.speak("taking you to privacy policy of farmax.", TextToSpeech.QUEUE_FLUSH, null);
}
case PHONE_SEARCH: {
Intent in = new Intent(this, MainMenu.class);
startActivity(in);
// t1.speak("Main Menu.", TextToSpeech.QUEUE_FLUSH, null);
break;
}
}
}
But the problem is that It doesnt wait for my command after it switches the menu.
Sometimes a toast pops up with "about" or sometimes with "ahead" even though I dont speak them. The app freezes badly after that and leaves me no other option than to close it.
If have also tried if else statements other than switch and case. But they don't seem to help much.
I have also tried to use the above code in onResult rather than onPartialResult but that doesnt help as well.
using sphinx tools I have created my own dictionary and grammar file.
Here is the grammar file content for this case.
#JSGF V1.0;
grammar firstscn;
public <item> = about | ahead;
Where am I going wrong? Please help me.
See code below. Pocketsphinx is configured with a keyphrase search to trigger on the word "record". Searching is then started, and talking causes onBeginningOfSpeech and onEndOfSpeech to be called, but no other listener methods get called, whatever I say.
public class MainActivity extends AppCompatActivity implements RecognitionListener {
private final Handler handler = new Handler ();
private SpeechRecognizer recognizer;
private final static String KEYWORD = "record";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
makeButtonStartButton ();
ensureRecordAudioPermission ();
startKeywordListener ();
}
private void startKeywordListener() {
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(MainActivity.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
Log.e("MainActivity", "Failed to init recognizer " + result);
} else {
startKeywordSearch ();
}
}
}.execute();
}
private void startKeywordSearch() {
Log.i("MainActivity", "Starting keyword search: " + KEYWORD);
recognizer.stop();
recognizer.startListening(KEYWORD);
}
private void setupRecognizer(File assetsDir) throws IOException {
// The recognizer can be configured to perform multiple searches
// of different kind and switch between them
recognizer = SpeechRecognizerSetup.defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
.setRawLogDir(assetsDir) // To disable logging of raw audio comment out this call (takes a lot of space on the device)
.getRecognizer();
recognizer.addListener(this);
// Create keyword-activation search.
recognizer.addKeyphraseSearch(KEYWORD, KEYWORD);
}
private void ensureRecordAudioPermission() {
// Check if user has given permission to record audio
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 1);
return;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startKeywordListener();
} else {
finish();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (recognizer != null) {
recognizer.cancel();
recognizer.shutdown();
}
}
private void makeButtonStartButton() {
findViewById(R.id.startButton).setOnClickListener(startRecording);
}
private final View.OnClickListener startRecording = new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, RecordingActivity.class));
}
};
#Override
public void onBeginningOfSpeech() {
Log.i ("MainActivity", "Beginning of speech detected");
}
#Override
public void onEndOfSpeech() {
Log.i ("MainActivity", "End of speech detected");
}
#Override
public void onPartialResult(Hypothesis hypothesis) {
if (hypothesis == null) return; // reject the null hypothesis (!)
Log.i ("MainActivity", "Partial result: " + hypothesis.getHypstr() + " (" + hypothesis.getProb() + ")");
if (hypothesis.getHypstr().equals(KEYWORD))
startRecording.onClick(null);
}
#Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis == null) return; // reject the null hypothesis (!)
Log.i ("MainActivity", "Complete result: " + hypothesis.getHypstr() + " (" + hypothesis.getProb() + ")");
if (hypothesis.getHypstr().equals(KEYWORD))
startRecording.onClick(null);
}
#Override
public void onError(Exception e) {
Log.i ("MainActivity", "Error detected", e);
}
#Override
public void onTimeout() {
Log.i ("MainActivity", "Timeout occurred");
}
}
I am trying to implement a hotword in my app which will start the speech input using CMUSphinx. I copied the code from the tutorial, did some changes to start the speech input but it is not working. My mainActivity code for the recognition looks something like this:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (PrefManager.getString(Constant.ACCESS_TOKEN, null) == null) {
throw new IllegalStateException("Not signed in, Cannot access resource!");
}
clientBuilder = new ClientBuilder();
init();
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
return;
}
runRecognizerSetup();
}
private static final String KWS_SEARCH = "wakeup";
private void runRecognizerSetup() {
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(MainActivity.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
Toast.makeText(getApplicationContext(),"Failed",LENGTH_SHORT).show();
} else {
switchSearch(KWS_SEARCH);
}
}
}.execute();
}
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
runRecognizerSetup();
} else {
finish();
}
}
}
/**
* 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();
if (text.equals(KEYPHRASE))
promptSpeechInput();
}
/**
* This callback is called when we stop the recognizer.
*/
#Override
public void onResult(Hypothesis hypothesis){
if (hypothesis != null) {
String pqr = hypothesis.getHypstr();
Toast.makeText(getApplicationContext(),pqr,LENGTH_SHORT).show();
}
}
#Override
public void onBeginningOfSpeech() {
}
/**
* We stop recognizer here to get a final result
*/
#Override
public void onEndOfSpeech() {
if (!recognizer.getSearchName().equals(KWS_SEARCH))
switchSearch(KWS_SEARCH);
}
private void switchSearch(String searchName) {
recognizer.stop();
// If we are not spotting, start listening with timeout (10000 ms or 10 seconds).
if (searchName.equals(KWS_SEARCH))
recognizer.startListening(searchName);
else
recognizer.startListening(searchName, 10000);
}
private void setupRecognizer(File assetsDir) throws IOException {
// The recognizer can be configured to perform multiple searches
// of different kind and switch between them
recognizer = SpeechRecognizerSetup.defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
.setRawLogDir(assetsDir) // To disable logging of raw audio comment out this call (takes a lot of space on the device)
.getRecognizer();
recognizer.addListener(this);
/** In your application you might not need to add all those searches.
* They are added here for demonstration. You can leave just one.
*/
// Create keyword-activation search.
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
}
#Override
public void onError(Exception error) {
Toast.makeText(getApplicationContext(),"error",LENGTH_SHORT).show();
}
#Override
public void onTimeout() {
switchSearch(KWS_SEARCH);
}
My keyphrase is "HI". The problem is that whenever I run this code I get a toast message "failed" due to this:
Toast.makeText(getApplicationContext(),"Failed",LENGTH_SHORT).show();
What can be possibly wrong with this?
I am very new to these things so any help in this will be really helpful.
Thank you.
I am using the default dictionary that comes with the pocketsphinx demo which is good for my purposes. When a user enters a phrase, the app starts a keyphrase listening but if the word is not found in the dictionary the app crashes. The app crashes onError() within a service. How is the error handling done? is there any way I can catch the error? Overall I would just like the service to call stopSelf() when an error happens so the main activity won't crash as well.
Errors:
ERROR: "kws_search.c", line 165: The word 'phonez' is missing in the dictionary
Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 5389 (1994.wherephone)
Here is my service class:
public class WherePhoneService extends Service implements RecognitionListener {
private static String SettingStorage = "SavedData";
SharedPreferences settingData;
private SpeechRecognizer recognizer;
private String sInput;
private String sOutput;
private int seekVal;
private TextToSpeech reply;
private AsyncTask t;
public WherePhoneService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
makeText(getApplicationContext(), "onHandle start", Toast.LENGTH_SHORT).show();
getValues();
startTTS();
t = new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(WherePhoneService.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
//((TextView) findViewById(R.id.caption_text)).setText("Failed to init recognizer " + result);
} else {
switchSearch(sInput);
}
}
}.execute();
return Service.START_STICKY;
}
private void setupRecognizer(File assetsDir) throws IOException {
recognizer = defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
// To disable logging of raw audio comment out this call (takes a lot of space on the device)
//.setRawLogDir(assetsDir)
// Threshold to tune for keyphrase to balance between false alarms and misses
.setKeywordThreshold(1e-45f)
// Use context-independent phonetic search, context-dependent is too slow for mobile
.setBoolean("-allphone_ci", true)
.getRecognizer();
recognizer.addListener(this);
// Create keyword-activation search.
recognizer.addKeyphraseSearch(sInput, sInput);
}
private void switchSearch(String searchName) {
recognizer.stop();
// If we are not spotting, start listening with timeout (10000 ms or 10 seconds).
if (searchName.equals(sInput))
recognizer.startListening(searchName);
else
recognizer.startListening(searchName, 10000);
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onEndOfSpeech() {
if (!recognizer.getSearchName().equals(sInput))
switchSearch(sInput);
}
#Override
public void onPartialResult(Hypothesis hypothesis) {
if (hypothesis == null)
return;
String text = hypothesis.getHypstr();
makeText(getApplicationContext(), "Partial", Toast.LENGTH_SHORT).show();
if (text.equals(sInput)) {
setVolume();
// Text to speech
reply.speak(sOutput, TextToSpeech.QUEUE_ADD, null);
switchSearch(sInput);
}
else {
makeText(getApplicationContext(), "Try again", Toast.LENGTH_SHORT).show();
switchSearch(sInput);
}
}
#Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
// restart listener and affirm that partial has past
makeText(getApplicationContext(), "end", Toast.LENGTH_SHORT).show();
//recognizer.startListening(sInput);
switchSearch(sInput);
}
}
public void onError(Exception e) {
e.printStackTrace(); // not all Android versions will print the stack trace automatically
Intent intent = new Intent ();
intent.setAction ("com.mydomain.SEND_LOG"); // see step 5.
intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK); // required when starting from Application
startActivity (intent);
stopSelf();
}
#Override
public void onTimeout() {
switchSearch(sInput);
}
public void startTTS() {
reply = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
reply.setLanguage(Locale.UK);
}
}
});
}
public void getValues() {
settingData = getBaseContext().getSharedPreferences(SettingStorage, 0);
sInput = settingData.getString("inputstring", "Where is my phone").toString().toLowerCase().replaceAll("[^\\w\\s]", "");
sOutput = settingData.getString("outputstring", "").toString().toLowerCase();
seekVal = settingData.getInt("seekval", 0);
}
public void setVolume() {
int seekValConvert = 0;
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int getMaxPhoneVol = audioManager.getStreamMaxVolume(audioManager.STREAM_MUSIC);
seekValConvert = ((seekVal * getMaxPhoneVol)/100);
audioManager.setStreamVolume(audioManager.STREAM_MUSIC, seekValConvert, 0);
}
#Override
public void onDestroy() {
super.onDestroy();
makeText(getApplicationContext(), "destroy", Toast.LENGTH_SHORT).show();
recognizer.cancel();
recognizer.shutdown();
t.cancel(true);
}
}
Crash is a bug in pocketsphinx-android. If you update to latest version from github, it should properly throw RuntimeException on any errors in methods addKeyphrase and setSearch.