1

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

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

pocketSphinxAndroidDemo-preAlpha 项目

Android 文本转语音教程项目

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

 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<String, Integer> captions;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main_sms);  

        new AsyncTask<Void, Void, Exception>() {
            @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

    }
}
4

2 回答 2

0

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

您也没有正确使用pocketsphinx。您需要在关键字识别模式下使用 pocketsphinx 来识别您想要识别的所有三个短语。

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

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");
}
于 2015-03-15T15:25:53.607 回答
0

实际上,阈值频率在pocketsphinx中逐字改变。我将它用于始终收听功能以查找放错位置的 android 手机。希望对你有帮助:

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

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

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

于 2016-05-11T08:54:19.510 回答