在Cupcake中,Android引入了对语音识别的支持。为了进行语音识别,以语音拨号为例,在语音识别引擎中,首先要启动麦克风,然后创建一个语音识别器,接着扫描电话本,查看语法分析数据库g2g文件是否陈旧。如果陈旧,则重构g2g文件,否则就加载g2g文件。然后启动语音识别器,进行语音的捕获并等待处理结果。当处理完成后,语音识别引擎会返回一组Intent,后停止麦克风和语音识别器。对语音拨号的具体处理过程如下:
public void recognize(VoiceDialerActivity voiceDialerActivity,File micFile, File contactsFile, String codec)
{
InputStream mic=null;
boolean recognizerStarted=false;
try {
if (Config.LOGD) Log.d(TAG, "start");
mVoiceDialerActivity=voiceDialerActivity; //启动voiceDialerActivity
mLogger=null;
if (RecognizerLogger.isEnabled(mVoiceDialerActivity))
{
mLogger=new RecognizerLogger(mVoiceDialerActivity);
}
if (Config.LOGD) Log.d(TAG, "start new MicrophoneInputStream");
if (micFile !=null)
{
mic=new FileInputStream(micFile); //创建输入流
WaveHeader hdr=new WaveHeader(); //音频格式为WAV
hdr.read(mic); //设置输入设备
}
else
{
mic=new MicrophoneInputStream(SAMPLE_RATE, SAMPLE_RATE * 15);
}
voiceDialerActivity.onMicrophoneStart(); //提醒用户输入语音
//创建新识别器
if (Config.LOGD) Log.d(TAG, "start new Recognizer");
if (mSrec==null) mSrec=new Recognizer(SREC_DIR + "/baseline11k.par");
if (Config.LOGD) Log.d(TAG, "start getVoiceContacts");
List contacts=contactsFile !=null ?
VoiceContact.getVoiceContactsFromFile(contactsFile) :
VoiceContact.getVoiceContacts(mVoiceDialerActivity);
if (mLogger !=null) mLogger.logContacts(contacts);
//产生g2g语法文件名
File g2g=mVoiceDialerActivity.getFileStreamPath("voicedialer."+Integer.toHexString(contacts.hashCode()) + ".g2g");
//如果当前g2g文件过期,重构g2g文件
if (!g2g.exists())
{
deleteAllG2GFiles(mVoiceDialerActivity);
if (mSrecGrammar !=null)
{
mSrecGrammar.destroy();
mSrecGrammar=null;
}
//加载空语法器
if (Config.LOGD) Log.d(TAG, "start new Grammar");
mSrecGrammar=mSrec.new Grammar(SREC_DIR + "/grammars/VoiceDialer.g2g"); //语法分析数据库VoiceDialer.g2g"
mSrecGrammar.setupRecognizer(); ///启动语音识别器
if (Config.LOGD) Log.d(TAG, "start grammar.resetAllSlots");
mSrecGrammar.resetAllSlots();
addOpenEntriesToGrammar();
addNameEntriesToGrammar(contacts);
//编译语法器
if (Config.LOGD) Log.d(TAG, "start grammar.compile");
mSrecGrammar.compile();
//更新g2g文件
if (Config.LOGD) Log.d(TAG, "start grammar.save " + g2g.getPath());
g2g.getParentFile().mkdirs();
mSrecGrammar.save(g2g.getPath());
}
else if (mSrecGrammar==null)
{
if (Config.LOGD) Log.d(TAG, "start new Grammar loading " + g2g);
mSrecGrammar=mSrec.new Grammar(g2g.getPath());
mSrecGrammar.setupRecognizer();
}
//启动识别过程
if (Config.LOGD) Log.d(TAG, "start mSrec.start");
mSrec.start();
recognizerStarted=true;
if (mLogger !=null) mic=mLogger.logInputStream(mic, SAMPLE_RATE);
while (true) {
if (Thread.interrupted()) throw new InterruptedException();
int event=mSrec.advance();
if (event !=Recognizer.EVENT_INCOMPLETE &&event !=Recognizer.EVENT_NEED_MORE_AUDIO)
{
if (Config.LOGD) Log.d(TAG, "start advance()="+Recognizer.eventToString(event));
}
switch (event) {
case Recognizer.EVENT_INCOMPLETE:
case Recognizer.EVENT_STARTED:
case Recognizer.EVENT_START_OF_VOICING:
case Recognizer.EVENT_END_OF_VOICING:
continue;
case Recognizer.EVENT_RECOGNITION_RESULT:
onRecognitionSuccess(); //识别结果
break;
case Recognizer.EVENT_NEED_MORE_AUDIO:
mSrec.putAudio(mic); //继续输入语音
continue;
default:
mVoiceDialerActivity.onRecognitionFailure(Recognizer.eventToString(event));
break;
}
break;
}
}
catch (InterruptedException e)
{
if (Config.LOGD) Log.d(TAG, "start interrupted "+e);
}
catch(IOException e)
{
if (Config.LOGD) Log.d(TAG, "start new Srec failed "+e);
mVoiceDialerActivity.onRecognitionError(e.toString());
}
finally {
//停止麦克风
try {
if (mic !=null) mic.close();
}
catch (IOException ex)
{
if (Config.LOGD) Log.d(TAG, "start - mic.close failed - " + ex);
}
mic=null;
//关闭识别器
if (Config.LOGD) Log.d(TAG, "start mSrec.stop");
if (mSrec !=null && recognizerStarted) mSrec.stop();
try {
if (mLogger !=null) mLogger.close();
}
catch (IOException ex)
{
if (Config.LOGD) Log.d(TAG, "start - mLoggger.close failed - " + ex);
}
mLogger=null;
}
if (Config.LOGD) Log.d(TAG, "start bye");
}