一起运行Pocketsphinx和Google TTS

我想开始一个新的活动,从一开始就识别语音,并且可以在活动开始后立即读取传入的消息。

此代码是从默认值合并的代码。 它在默认情况下运行良好。 但我想删除按钮作为触发器,而是使用语音来触发SMSReaderMain.java进一步操作。 因此,我使用pocketphinx for Android来实现它。

pocketSphinxAndroidDemo-preAlpha项目

Android文本到Speech Tutorial项目

它没有给我任何错误,但是当它在实际设备上运行时,它强制关闭。 Log cat显示这些错误

  03-16 23:09:15.330: E/cmusphinx(8505): ERROR: "kws_search.c", line 158: The word '/1e-60/' is missing in the dictionary 03-16 23:09:15.330: E/cmusphinx(8505): ERROR: "kws_search.c", line 158: The word '/1e-60/' is missing in the dictionary 03-16 23:09:15.330: I/cmusphinx(8505): INFO: kws_search.c(417): KWS(beam: -1080, plp: -23, default threshold -450) 03-16 23:09:15.330: E/cmusphinx(8505): ERROR: "kws_search.c", line 158: The word '/1e-60/' is missing in the dictionary 03-16 23:09:15.330: E/cmusphinx(8505): ERROR: "kws_search.c", line 158: The word '/1e-60/' is missing in the dictionary 03-16 23:09:15.330: I/cmusphinx(8505): INFO: kws_search.c(417): KWS(beam: -1080, plp: -23, default threshold -450) 03-16 23:09:15.330: E/cmusphinx(8505): ERROR: "kws_search.c", line 158: The word '/1e-60/' is missing in the dictionary 03-16 23:09:15.330: E/cmusphinx(8505): ERROR: "kws_search.c", line 158: The word '/1e-60/' is missing in the dictionary 03-16 23:09:15.340: I/TextToSpeech(8505): Set up connection to ComponentInfo{com.svox.pico/com.svox.pico.PicoService} 03-16 23:09:15.340: I/TextToSpeech(8505): Set up connection to ComponentInfo{com.svox.pico/com.svox.pico.PicoService} 

请帮我举个例子。 你能帮帮我哪里出错吗? 这是我的代码:

SMSReaderMain.java

  package edu.cmu.pocketsphinx.demo; import static android.widget.Toast.makeText; import static edu.cmu.pocketsphinx.SpeechRecognizerSetup.defaultSetup; import java.io.File; import java.io.IOException; import java.util.HashMap; import android.app.Activity; import edu.cmu.pocketsphinx.Assets; import edu.cmu.pocketsphinx.Hypothesis; import edu.cmu.pocketsphinx.RecognitionListener; import edu.cmu.pocketsphinx.SpeechRecognizer; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.provider.ContactsContract; import android.provider.ContactsContract.PhoneLookup; import android.speech.tts.TextToSpeech; import android.telephony.SmsMessage; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; //import android.widget.CompoundButton; //import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.TextView; import android.widget.Toast; //import android.widget.ToggleButton; public class SMSReaderMain extends Activity implements RecognitionListener { private final int CHECK_CODE = 0x1; private final int LONG_DURATION = 5000; private final int SHORT_DURATION = 1200; private Speaker speaker; private TextView smsText; private TextView smsSender; private BroadcastReceiver smsReceiver; public static final String TURNON_SR = "drive mode"; public static final String TURNOFF_SR = "disable drive mode"; public static final String DESTROY_SR = "exit drive mode"; public SpeechRecognizer recognizer; public HashMap captions; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_sms); new AsyncTask() { @Override protected Exception doInBackground(Void... params) { try { Assets assets = new Assets(SMSReaderMain.this); File assetDir = assets.syncAssets(); setupRecognizer(assetDir); } catch (IOException e) { return e; } return null; } }.execute(); //toggle = (ToggleButton)findViewById(R.id.speechToggle); smsText = (TextView)findViewById(R.id.sms_text); smsSender = (TextView)findViewById(R.id.sms_sender); startDriveMode(); checkTTS(); initializeSMSReceiver(); registerSMSReceiver(); } private void startDriveMode(){ speaker = new Speaker(this); speaker.allow(true); speaker.speak(getString(R.string.start_speaking)); //speaker.speak("Drive mode now will be enabled. I will read your new messages for you now"); } private void checkTTS(){ Intent check = new Intent(); check.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); startActivityForResult(check, CHECK_CODE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == CHECK_CODE){ if(resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS){ speaker = new Speaker(this); }else { Intent install = new Intent(); install.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); startActivity(install); } } } private void initializeSMSReceiver(){ smsReceiver = new BroadcastReceiver(){ @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if(bundle!=null){ Object[] pdus = (Object[])bundle.get("pdus"); for(int i=0;i<pdus.length;i++){ byte[] pdu = (byte[])pdus[i]; SmsMessage message = SmsMessage.createFromPdu(pdu); String text = message.getDisplayMessageBody(); String sender = getContactName(message.getOriginatingAddress()); speaker.pause(LONG_DURATION); speaker.speak("You have a new message from" + sender + "!"); speaker.pause(SHORT_DURATION); speaker.speak(text); smsSender.setText("Message from " + sender); smsText.setText(text); } } } }; } private void registerSMSReceiver() { IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); registerReceiver(smsReceiver, intentFilter); } private String getContactName(String phone){ Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phone)); String projection[] = new String[]{ContactsContract.Data.DISPLAY_NAME}; Cursor cursor = getContentResolver().query(uri, projection, null, null, null); if(cursor.moveToFirst()){ return cursor.getString(0); }else { return "unknown number"; } } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(smsReceiver); speaker.destroy(); } public void onPartialResult(Hypothesis hypothesis) { String text = hypothesis.getHypstr(); try { Intent i= null; if (text.equals("drive mode")) { recognizer.cancel(); popPicture(); startDriveMode(); } if (text.equals("disable drive mode")) { speaker = new Speaker(this); speaker.speak(getString(R.string.stop_speaking)); speaker.allow(false); //popPicture2(); } if (text.equals("exit drive mode")) { recognizer.cancel(); i = new Intent(getApplicationContext(),PocketSphinxActivity.class); startActivity(i); onDestroy(); //popPicture2(); } } catch (Exception e) { e.printStackTrace(); } } public void popPicture() { LayoutInflater inflater = getLayoutInflater(); View layout = inflater.inflate(R.layout.toast_image,(ViewGroup) findViewById(R.id.toast_layout_id)); Toast toast = new Toast(getApplicationContext()); toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0); toast.setDuration(Toast.LENGTH_SHORT); toast.setView(layout); toast.show(); } public void onResult(Hypothesis hypothesis) { ((TextView) findViewById(R.id.result_text)).setText(""); if (hypothesis != null) { String text = hypothesis.getHypstr(); makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show(); } } public void switchSearch(String searchName) { recognizer.stop(); recognizer.startListening(searchName); String caption = getResources().getString(captions.get(searchName)); ((TextView) findViewById(R.id.caption_text)).setText(caption); } public void setupRecognizer(File assetsDir) { File modelsDir = new File(assetsDir, "models"); recognizer = defaultSetup() .setAcousticModel(new File(modelsDir, "hmm/en-us-semi")) .setDictionary(new File(modelsDir, "dict/cmu07a.dic")) .setRawLogDir(assetsDir).setKeywordThreshold(1e-20f) .getRecognizer(); recognizer.addListener(this); // Create grammar-based searches. recognizer.addKeywordSearch(TURNON_SR, new File(modelsDir, "keywords.list")); recognizer.addKeywordSearch(TURNOFF_SR, new File(modelsDir, "keywords.list")); recognizer.addKeywordSearch(DESTROY_SR, new File(modelsDir, "keywords.list")); //File menuGrammar = new File(modelsDir, "grammar/sms.gram"); // recognizer.addGrammarSearch(TURNOFF_SR, menuGrammar); //recognizer.addGrammarSearch(TURNON_SR, menuGrammar); //recognizer.addGrammarSearch(DESTROY_SR, menuGrammar); } @Override public void onBeginningOfSpeech() { // TODO Auto-generated method stub } @Override public void onEndOfSpeech() { // TODO Auto-generated method stub } } 

错误是您没有在第98行初始化speaker字段,因此它的值为null,因此您有一个空指针exception。 您需要在使用之前初始化变量。

你也没有正确使用pocketsphinx。 您需要在关键字定位模式中使用pocketsphinx以及您想要识别的所有三个短语。

您需要在assets/sync/model文件夹中创建一个文件keywords.list ,如下所示的关键短语:

 drive mode /1e-40/ disable drive mode /1e-40/ exit drive mode /1e-40/ 

这里的数字是检测阈值。 您可以尝试1e-20或1e-60等值,并调整阈值以获得检测和误报之间的最佳平衡。

然后你需要将这个短语列表设置为关键词搜索,不需要使用3个语法搜索,你可以用3个关键短语运行一个搜索:

 recognizer.addKeywordSearch("commands", new File(modelDir, "keywords.list"); 

这样,您将配置识别器以查找3个命令并忽略其他所有命令。

现在,您可以在onPartialResult方法中处理结果,其中报告检测:

 public void onPartialResult(Hypothesis hypothesis) { String text = hypothesis.getHypstr(); if (text.equals("start drive mode") { recognizer.cancel(); // stop pocketsphinx startDriveMode(); // starting any other actions including speech recognition } .... } 

如果要重新启动搜索,可以调用recognizer.startSearch("commands");

 public void startDriveMode() { // do whatever you want here, use Google TTS recognizer.startSearch("commands"); } 

实际上,阈值频率在pocketsphinx中逐字逐句变化。 我用它总是听function找到错位的Android手机。 希望对你有帮助:

https://github.com/manmaybarot/where-is-my-phone-Android-App

  • 你不能将手机麦克风用于不同的库,例如tts和pocketsphinx。 如果你这样做,你可能会收到“麦克风已经在使用”的错误

  • PocketSphinx适合男性声音,但不适合识别女性声音。